package com.videogo.openapi;

import android.app.Application;
import android.content.Context;
import android.os.Handler;
import android.text.TextUtils;

import com.ezviz.sdk.configwifi.touchAp.GetAccessDeviceInfoCallback;
import com.ezviz.sdk.configwifi.touchAp.GetDeviceWifiListCallback;
import com.ezviz.sdk.configwifi.touchAp.GetTokenCallback;
import com.ezviz.sdk.configwifi.touchAp.QueryPlatformBindStatusCallback;
import com.ezviz.sdk.configwifi.touchAp.StartNewApConfigCallback;
import com.hikvision.wifi.configuration.DeviceDiscoveryListener;
import com.videogo.auth.EZAuthApi;
import com.videogo.ezdclog.EZDcLogManager;
import com.videogo.openapi.bean.EZAccessTokenInternal;
import com.videogo.util.LocalInfo;
import com.videogo.constant.Config;
import com.videogo.errorlayer.ErrorLayer;
import com.videogo.errorlayer.ErrorOpenSDKProxy;
import com.videogo.exception.BaseException;
import com.videogo.main.AppManager;
import com.videogo.openapi.bean.EZAccessToken;
import com.videogo.openapi.bean.EZAlarmInfo;
import com.videogo.openapi.bean.EZAreaInfo;
import com.videogo.openapi.bean.EZCloudRecordFile;
import com.videogo.openapi.bean.EZDeviceCloudServiceInfo;
import com.videogo.openapi.bean.EZDeviceInfo;
import com.videogo.openapi.bean.EZDeviceRecordFile;
import com.videogo.openapi.bean.EZDeviceUpgradeStatus;
import com.videogo.openapi.bean.EZDeviceVersion;
import com.videogo.openapi.bean.EZHiddnsDeviceInfo;
import com.videogo.openapi.bean.EZLeaveMessage;
import com.videogo.openapi.bean.EZProbeDeviceInfo;
import com.videogo.openapi.bean.EZProbeDeviceInfoResult;
import com.videogo.openapi.bean.EZStorageStatus;
import com.videogo.openapi.bean.EZUserInfo;
import com.videogo.util.LogUtil;
import com.videogo.wificonfig.APWifiConfig;
import com.videogo.wificonfig.ConfigWifiSdkManager;

import java.util.Calendar;
import java.util.List;

/**
 * 开放平台海外版本
 * 海外开发者接入时关注此接口(EZOpenSDK是面向国内开发者的)
 * <p>
 * Created by yudan on 16/7/7.
 */
public final class EZGlobalSDK extends EZOpenSDK {

    private static final String TAG = "EZGlobalSDK";
    private static final String API_URL = "https://open.ezvizlife.com";
    private static final String WEB_URL = "https://openauth.ezvizlife.com";

//    static {
//        System.loadLibrary("stlport_shared");
//        System.loadLibrary("marsxlog");
//    }

    private EZGlobalSDK(Application application, String appKey) {
        super(application, appKey);
        LogUtil.i(TAG, "construct EZGlobalSDK, version: " + getVersion());
    }

    public static EZGlobalSDK getInstance() {
        return (EZGlobalSDK) mEZOpenSDK;
    }

    // 据底底层库同事描述该接口主要用于热更新，SDK暂无此需求，因此移除该接口
//    /**
//     * SDK 初始化
//     *
//     * @param application  客戶端app的 Application 對象
//     * @param appKey  客戶端app申請的app key
//     * @param loadLibraryAbsPath  如果将so库放到sd卡上，此处指定.so库在sd卡的路径
//     *
//     * @return  true 表示成功，false 表示失败
//     */
//    public static boolean initLib(Application application, String appKey, String loadLibraryAbsPath) {
//        if (TextUtils.isEmpty(appKey)){
//            LogUtil.e(TAG,"initLib EZOpenSDK, appKey is null");
//            return false;
//        }
//        // 创建LocalInfo对象并初始化
//        LocalInfo.init(application);
//        LocalInfo.getInstance().setServAddr(API_URL);
//        LocalInfo.getInstance().setAuthServAddr(WEB_URL);
//        if (!TextUtils.isEmpty(loadLibraryAbsPath)) {
//            EzvizAPI.init(application, appKey, loadLibraryAbsPath);
//        } else {
//            EzvizAPI.init(application, appKey);
//        }
//        EzvizAPI.getInstance().setServerUrl(API_URL, WEB_URL);
//        EzvizAPI.getInstance().setAccessToken(LocalInfo.getInstance().getEZAccesstoken().getAccessToken());
//        EzvizAPI.platformType = EZConstants.EZPlatformType.EZPlatformTypeGLOBALSDK;
//        AppManager.getInstance().getEZSDKConfigurationSyn();
//        if (mGlobalSDK == null) {
//            mGlobalSDK = new EZGlobalSDK();
//        }
//
//        return true;
//    }

    /**
     * @deprecated 不再支持加载外置so库，仅保留形式兼容老版本sdk
     */
    @Deprecated
    public static boolean initLib(Application application, String appKey, String loadLibraryAbsPath) {
        return initLib(application, appKey);
    }

    /**
     * SDK 初始化
     *
     * @param application 客戶端app的 Application 對象
     * @param appKey      客戶端app申請的app key
     * @return true 表示成功，false 表示失败
     */
    public static boolean initLib(Application application, String appKey) {
        if (TextUtils.isEmpty(appKey)) {
            LogUtil.e(TAG, "initLib EZOpenSDK, appKey is null");
            return false;
        }

        ErrorLayer.setErrorProxy(ErrorOpenSDKProxy.getInstance());

        // 创建LocalInfo对象并初始化
        LocalInfo.init(application, appKey);
        LocalInfo.getInstance().setServAddr(API_URL);
        LocalInfo.getInstance().setAuthServAddr(WEB_URL);
        EzvizAPI.init(application, appKey, true);
        EzvizAPI.getInstance().setServerUrl(API_URL, WEB_URL);
        EzvizAPI.getInstance().preSetToken();
//        EZDcLogManager.getInstance().setUsingGlobalSDK(true);
        EZAuthApi.platformType = EZPlatformType.EZPlatformTypeGLOBALSDK;

        AppManager.getInstance().getEZSDKConfigurationSyn();
        mEZOpenSDK = new EZGlobalSDK(application, appKey);

        showSDKLog(Config.LOGGING);

        return true;
    }

    /**
     * 打开云存储H5页面
     * 仅适用于单通道设备，如IPC，不建议使用
     *
     * @param deviceSerial 设备序列号
     * @throws BaseException 调用失败的异常信息
     * @deprecated 仅保留接口兼容老用户，请尽快换用void openCloudPage(String deviceSerial, int cameraNo)
     */
    @Deprecated
    public void openCloudPage(String deviceSerial) throws BaseException {
        mEzvizAPI.openCloudPage(deviceSerial, 1);
    }

    /**
     * 打开云存储H5页面
     *
     * @param deviceSerial 设备序列号
     * @param cameraNo     camera序号，EZCameraInfo.cameraNo
     * @throws BaseException 调用失败的异常信息
     * @since 4.8.8 增加camera序号
     */
    public void openCloudPage(String deviceSerial, int cameraNo) throws BaseException {
        mEzvizAPI.openCloudPage(deviceSerial, cameraNo);
    }

    /**
     * 释放sdk资源
     */
    public static void finiLib() {
        LogUtil.i(TAG, "FiniLib EZGlobalSDK, version: " + getVersion());
    }

    public static String getVersion() {
        return Config.VERSION;
    }

    /**
     * 设置是否支持P2P取流，默认是不支持的
     * P2P取流可以降低转发取流的比例，但是在多人同时观看时对设备端的带宽要求也更高，设备端带宽不够的情况下，影响播放体验
     * 对于可能多人同时观看的场景，建议不支持
     * 对于家用监控类的场景，建议支持P2P
     * 此函数可以在任意时刻调用
     *
     * @param bEnable true-支持p2p false-不支持p2p
     */
    public static void enableP2P(boolean bEnable) {
        Config.ENABLE_P2P = bEnable;
    }

    /**
     * 授权登录以后给EZOpenSDK设置AccessToken
     *
     * @param accessToken 授权登录获取的accessToken
     */
    public void setAccessToken(String accessToken) {
        mEzvizAPI.setAccessToken(accessToken);
    }

    /**
     * 获取登录token
     *
     * @return token包含2个字段，
     * 一个是token string本身，另外一个表示过期时间，单位为秒
     */
    public EZAccessToken getEZAccessToken() {
        return mEzvizAPI.getEZAccessToken();
    }

    /**
     * 获取区域列表
     * 接口中有网络操作，需要在线程中调用
     *
     * @return 区域列表
     * @throws BaseException
     * @see EZAreaInfo
     */
    public List<EZAreaInfo> getAreaList() throws BaseException {
        return mEzvizAPI.getAreaList();
    }

    /**
     * 打开授权登录中间页面,用于获取Accesstoken
     *
     * @param areaId 区域ID
     */
    public void openLoginPage(int areaId) {
        mEzvizAPI.gotoLoginPage(false, areaId, -1);
    }

    /**
     * 打开授权登录中间页面,用于获取Accesstoken
     *
     * @param areaId 区域ID
     * @param flag   页面跳转flag 类似Intent.FLAG_ACTIVITY_CLEAR_TOP
     */
    public void openLoginPage(int areaId, int flag) {
        mEzvizAPI.gotoLoginPage(false, areaId, flag);
    }

    /**
     * 登出账号
     */
    public void logout() {
        mEzvizAPI.logout();
    }


    /**
     * 获取用户的设备列表，返回EZDeviceInfo的对象数组，只提供设备基础数据
     * 该接口为耗时操作，建议放在线程中调用
     *
     * @param pageIndex 查询页index，从0开始
     * @param pageSize  每页数量（建议20以内）
     * @return 返回的EZDeviceInfo
     * @throws BaseException
     */
    public List<EZDeviceInfo> getDeviceList(int pageIndex, int pageSize) throws BaseException {
        return mEzvizAPI.getDeviceList(pageIndex, pageSize, false);
    }


    /**
     * 尝试查询设备信息（用于添加设备之前, 简单查询设备信息，如是否在线，是否添加等）
     * 该接口为耗时操作，建议放在线程中调用
     *
     * @param deviceSerial 需要查询的设备序列号
     * @return 返回 EZProbeDeviceInfo 对象，包含设备简单信息，用于添加目的
     * @throws BaseException
     * @deprecated 仅保留接口兼容老用户，请尽快换用EZProbeDeviceInfoResult probeDeviceInfo(String deviceSerial,String deviceType)
     */
    @Deprecated
    public EZProbeDeviceInfo probeDeviceInfo(String deviceSerial) throws BaseException {
        return mEzvizAPI.probeDeviceInfo(deviceSerial);
    }

    /**
     * 尝试查询设备信息（用于添加设备之前, 简单查询设备信息，如是否在线，是否添加等）
     * 接口中有网络操作，需要在线程中调用
     *
     * @param deviceSerial 需要查询的设备序列号
     * @return 返回 EZProbeDeviceInfoResult 对象，包含查询的设备信息，以及异常情况
     */
    public EZProbeDeviceInfoResult probeDeviceInfo(String deviceSerial, String deviceType) {
        return mEzvizAPI.probeDeviceInfo(deviceSerial, deviceType);
    }

    /**
     * 尝试查询设备信息（用于添加设备之前, 简单查询设备信息，如是否在线，是否添加等）
     * 该接口为耗时操作，必须在线程中调用
     *
     * @param deviceSerial 需要查询的设备序列号
     * @param deviceType   设备型号 (设备型号和设备序列号不能均为空,优先按照设备序列号查询)
     * @param apiUrl       指定去哪个平台查询
     * @return 返回 EZProbeDeviceInfo 对象，包含设备简单信息，用于添加目的
     */
    public EZProbeDeviceInfoResult probeDeviceInfo(String deviceSerial, String deviceType, String apiUrl) {
        return mEzvizAPI.probeDeviceInfo(deviceSerial, deviceType, apiUrl);
    }

    /**
     * 获取告警信息列表
     * 接口中有网络操作，需要在线程中调用
     *
     * @param deviceSerial 设备序列号，为null时查询整个账户下的告警信息列表
     * @param pageIndex    分页当前页码（从0开始）
     * @param pageSize     分页每页数量（建议20以内）
     * @param beginTime    搜索时间范围开始时间，开始时间和结束时间可以同时为空
     * @param endTime      搜索时间范围结束时间
     * @return EZAlarmInfo对象列表
     * @throws BaseException
     */
    public List<EZAlarmInfo> getAlarmList(String deviceSerial, int pageIndex, int pageSize, Calendar beginTime,
                                          Calendar endTime) throws BaseException {
        return mEzvizAPI.getAlarmList(deviceSerial, pageIndex, pageSize, beginTime, endTime);
    }

    /**
     * 设置告警为已读
     * 接口中有网络操作，需要在线程中调用
     *
     * @param alarmIdList 告警信息Id数组(设置单条告警为已读时，数组中可以只有一个Id)
     * @param alarmStatus 告警状态,目前只支持设为已读功能 EZMessageStatusRead
     * @return true 表示成功， false 表示失败
     * @throws BaseException
     */
    public boolean setAlarmStatus(List<String> alarmIdList, EZConstants.EZAlarmStatus alarmStatus) throws BaseException {
        return mEzvizAPI.setAlarmStatus(alarmIdList, alarmStatus);
    }

    /**
     * 批量删除告警
     *
     * @param alarmIdList 告警ID list
     * @return true 表示成功， false 表示失败
     * @throws BaseException
     */
    public boolean deleteAlarm(List<String> alarmIdList) throws BaseException {
        return mEzvizAPI.deleteAlarm(alarmIdList);
    }

    /**
     * 查询远程SD卡存储录像信息列表
     * 当设备关联了NVR存储设备后，此时查找的是NVR设备中录像，不再提供查找设备SD卡中录像
     * 接口中有网络操作，需要在线程中调用
     *
     * @param deviceSerial 设备序列号
     * @param cameraNo     camera的序号，EZCameraInfo.cameraNo
     * @param startTime    查询时间范围开始时间
     * @param endTime      查询时间范围结束时间
     * @return 远程SD卡存储录像信息列表
     * @throws BaseException
     */
    public List<EZDeviceRecordFile> searchRecordFileFromDevice(String deviceSerial, int cameraNo, Calendar startTime,
                                                               Calendar endTime) throws BaseException {
        return mEzvizAPI.searchRecordFileFromDevice(deviceSerial, cameraNo, startTime, endTime);
    }

    /**
     * 查询远程SD卡录像信息列表（支持获取浓缩录像）
     * 当设备关联了NVR存储设备后，此时查找的是NVR设备中录像，不再提供查找设备SD卡中录像
     * 该接口为耗时操作，必须在线程中调用
     *
     * @param deviceSerial    设备序列号
     * @param cameraNo        camera的序号，EZCameraInfo.cameraNo
     * @param startTime       查询时间范围开始时间
     * @param endTime         查询时间范围结束时间
     * @param videoRecordTypeEx 录像类型
     * @return 远程SD卡存储录像信息列表
     * @throws BaseException
     * @since v5.8
     */
    public List<EZDeviceRecordFile> searchRecordFileFromDeviceEx(String deviceSerial, int cameraNo, Calendar startTime, Calendar endTime, EZConstants.EZVideoRecordTypeEx videoRecordTypeEx)
            throws BaseException {
        return mEzvizAPI.searchRecordFileFromDeviceEx(deviceSerial, cameraNo, startTime, endTime, String.valueOf(videoRecordTypeEx.recordType));
    }

    /**
     * 添加设备
     * 接口中有网络操作，需要在线程中调用
     *
     * @param deviceSerial 设备序列号
     * @param verifyCode   设备验证码，验证码位于设备机身上，6位大写字母
     * @return true 表示成功， false 表示失败
     * @throws BaseException
     */
    public boolean addDevice(String deviceSerial, String verifyCode) throws BaseException {
        return mEzvizAPI.addDeviceBySerialNonTransfer(deviceSerial, verifyCode);
    }

    /**
     * 删除当前账号的设备
     * 接口中有网络操作，需要在线程中调用
     *
     * @param deviceSerial 设备序列号, 9位数字
     * @return true 表示成功， false 表示失败
     * @throws BaseException
     */
    public boolean deleteDevice(String deviceSerial) throws BaseException {
        return mEzvizAPI.deleteDeviceNonTransfer(deviceSerial);
    }

    /**
     * PTZ 控制接口
     * 接口中有网络操作，需要在线程中调用
     *
     * @param deviceSerial 设备序列号
     * @param cameraNo     通道号
     * @param command      ptz控制命令
     * @param action       控制启动/停止
     * @param speed        速度（0-7）
     * @return 操作成功或者失败(返回失败错误码)
     */
    public boolean controlPTZ(String deviceSerial, int cameraNo, EZConstants.EZPTZCommand command,
                              EZConstants.EZPTZAction action, int speed) throws BaseException {
        return mEzvizAPI.controlPTZ(deviceSerial, cameraNo, command, action, speed);
    }

    /**
     * 镜像 控制设备视频画面翻转。在摄像头倒装的时候，调用此接口可让画面正过来
     * 需要设备支持
     * 该接口为耗时操作，必须在线程中调用
     *
     * @param deviceSerial 设备序列号
     * @param cameraNo     camera的序号，EZCameraInfo.cameraNo
     * @param command      ptz控制命令
     * @throws BaseException exception 操作失败会抛出异常，错误码 exception.getErrorCode
     * @deprecated 建议用http方式实现，使用说明请参考https://open.ys7.com/doc/zh/book/index/device_ptz.html#device_ptz-api3
     */
    @Deprecated
    public void controlVideoFlip(String deviceSerial, int cameraNo, EZConstants.EZPTZDisplayCommand command) throws BaseException {
        mEzvizAPI.controlVideoFlip(deviceSerial, cameraNo, command);
    }

    /**
     * 解密数据，该接口可以用于解密告警图片
     *
     * @param inputData  解密前数据
     * @param verifyCode 密码，设备加密时通常为设备验证码
     */
    public byte[] decryptData(byte[] inputData, String verifyCode) {
        return mEzvizAPI.decryptData(inputData, verifyCode, 1);
    }

    /**
     * 解密数据，该接口可以用于解密告警图片
     *
     * @param inputData  解密前数据
     * @param verifyCode 密码，设备加密时通常为设备验证码，平台加密时为平台返回的checkSum
     * @param cryptType  加密类型 1-设备加密 2-平台加密
     */
    public byte[] decryptData(byte[] inputData, String verifyCode, int cryptType) {
        return mEzvizAPI.decryptData(inputData, verifyCode, cryptType);
    }

    /**
     * 设备设置布防状态，兼容A1和IPC设备的布防
     * 接口中有网络操作，需要在线程中调用
     *
     * @param deviceSerial 设备序列号
     * @param defence      布防状态, 摄像机布防状态只有0和1，告警器有0:睡眠 8:在家 16:外出
     * @return
     * @throws BaseException
     */
    public boolean setDefence(String deviceSerial, EZConstants.EZDefenceStatus defence) throws BaseException {
        return mEzvizAPI.setDefence(deviceSerial, defence);
    }

    /**
     * 刷新设备详细信息（修改验证码后调用）
     * 接口中有网络操作，需要在线程中调用
     *
     * @param deviceSerial
     * @param cameraNo
     * @throws BaseException
     */
    public void refreshDeviceDetailInfo(String deviceSerial, int cameraNo) throws BaseException {
        mEzvizAPI.refreshDeviceDetailInfoEx(deviceSerial, cameraNo);
    }

    /**
     * 获取摄像头实时图片的url接口，需要设备支持，萤石设备一般都能支持此协议。(该功能和萤石云视频app首页刷新封面的功能一致)
     * 该接口为耗时操作，建议放在线程中调用
     *
     * @param deviceSerial 设备序列号
     * @param channelNo    通道号
     * @return 图片url
     * @throws BaseException
     */
    public String captureCamera(String deviceSerial, int channelNo) throws BaseException {
        return mEzvizAPI.capturePicture(deviceSerial, channelNo);
    }

    /**
     * 获取设备的版本信息接口
     * 接口中有网络操作，需要在线程中调用
     *
     * @param deviceSerial 设备序列号
     * @return 版本号EZDeviceVersion对象
     * @throws BaseException
     */
    public EZDeviceVersion getDeviceVersion(String deviceSerial) throws BaseException {
        return mEzvizAPI.getDeviceVersion(deviceSerial);
    }

    /**
     * 设备视频图片加解密开关接口
     * 接口中有网络操作，需要在线程中调用
     *
     * @param deviceSerial 设备序列号
     * @param validateCode 设备验证码，开启加密无需验证码
     * @param encrypt      是否加密
     * @return
     * @throws BaseException
     */
    public boolean setDeviceEncryptStatus(String deviceSerial, String validateCode, boolean encrypt) throws BaseException {

        return mEzvizAPI.setDeviceEncryptStatus(deviceSerial, validateCode, encrypt);
    }

    /**
     * 修改设备名称接口
     * 接口中有网络操作，需要在线程中调用
     *
     * @param deviceSerial 设备序列号
     * @param deviceName   修改后的设备名称
     * @return true 表示成功， false 表示失败
     * @throws BaseException
     */
    public boolean setDeviceName(String deviceSerial, String deviceName) throws BaseException {
        return mEzvizAPI.updateDeviceName(deviceSerial, deviceName);
    }

    /**
     * 获取用户信息；用户信息包含：用户名,头像地址等
     * 接口中有网络操作，需要在线程中调用
     *
     * @return 返回 EZUserInfo 对象
     * @throws BaseException
     */
    public EZUserInfo getUserInfo() throws BaseException {
        return mEzvizAPI.getEZUserInfo();
    }

    /**
     * 获取未读消息数
     * 接口中有网络操作，需要在线程中调用
     *
     * @param deviceSerial 需要获取的设备序列号，为空时返回账户下所有设备的未读消息数
     * @param messageType  消息类型：EZMessageTypeAlarm 告警消息，EZMessageTypeLeave 留言消息, 暂不支持
     * @return 未读消息数
     * @throws BaseException
     */
    public int getUnreadMessageCount(String deviceSerial, EZConstants.EZMessageType messageType) throws BaseException {
        return mEzvizAPI.getUnreadMessageCount(deviceSerial, messageType);
    }

    /**
     * 获取留言消息列表,默认为止查询语音留言信息
     * 该接口为耗时操作，建议放在线程中调用
     *
     * @param deviceSerial 设备序列号（可为空），为空时返回账户下所有设备的留言消息
     * @param pageIndex    当前分页，从0开始
     * @param pageSize     分页大小
     * @param beginTime    开始时间
     * @param endTime      结束时间
     * @return 留言EZLeaveMessage列表
     * @throws BaseException
     */
    public List<EZLeaveMessage> getLeaveMessageList(String deviceSerial, int pageIndex, int pageSize,
                                                    Calendar beginTime, Calendar endTime) throws BaseException {
        return mEzvizAPI.getLeaveMessageList(deviceSerial, pageIndex, pageSize, beginTime, endTime);
    }

    /**
     * 批量设置留言消息已读功能
     * 该接口为耗时操作，建议放在线程中调用
     *
     * @param msgIdList     留言消息Id数组(最大数量为10，允许只有1个)
     * @param messageStatus 需要设置的留言状态，目前只支持 EZMessageStatusRead(已读);
     * @return true 表示成功， false 表示失败
     * @throws BaseException
     */
    public boolean setLeaveMessageStatus(List<String> msgIdList, EZConstants.EZMessageStatus messageStatus) throws BaseException {
        return mEzvizAPI.setLeaveMessageStatus(msgIdList, messageStatus);
    }

    /**
     * 批量删除留言消息
     * 该接口为耗时操作，建议放在线程中调用
     *
     * @param msgIdList 留言消息Id数组(最大数量为10，允许只有1个)
     * @return true 表示成功， false 表示失败
     * @throws BaseException
     */
    public boolean deleteLeaveMessages(List<String> msgIdList) throws BaseException {
        return mEzvizAPI.deleteLeaveMessages(msgIdList);
    }

    /**
     * 获取语音留言数据
     * 该接口为耗时操作，建议放在线程中调用
     *
     * @param handler  handler，用于发送成功或者失败消息, 301:下载留言失败 ;302:下载留言成功 消息obj为留言ID
     * @param msg      留言消息
     * @param callback 获取留言消息数据回调
     */
    public void getLeaveMessageData(Handler handler, EZLeaveMessage msg,
                                    EZOpenSDKListener.EZLeaveMessageFlowCallback callback) {
        mEzvizAPI.getLeaveMessageData(handler, msg, callback);
    }


    /**
     * 获取存储介质状态(如是否初始化，格式化进度等)
     * 接口中有网络操作，需要在线程中调用
     *
     * @param deviceSerial 需要获取的设备序列号
     * @return 存储状态(EZStorageStatus)列表，列表每个item代表一个磁盘分区
     * @throws BaseException
     */
    public List<EZStorageStatus> getStorageStatus(String deviceSerial) throws BaseException {
        return mEzvizAPI.getStorageStatus(deviceSerial);
    }

    /**
     * 格式化分区(SD卡)
     * 接口中有网络操作，需要在线程中调用
     *
     * @param deviceSerial   需要格式化的设备序列号
     * @param partitionIndex getStorageStatus查询返回的分区号
     * @return true 表示成功， false 表示失败
     * @throws BaseException
     */
    public boolean formatStorage(String deviceSerial, int partitionIndex) throws BaseException {
        return mEzvizAPI.formatStorage(deviceSerial, partitionIndex);
    }

    /**
     * 开始升级设备
     * 接口中有网络操作，需要在线程中调用
     *
     * @param deviceSerial 设备序列号
     * @throws BaseException
     */
    public void upgradeDevice(String deviceSerial) throws BaseException {
        mEzvizAPI.upgradeDevice(deviceSerial);
    }

    /**
     * 获取设备升级状态
     * 接口中有网络操作，需要在线程中调用
     *
     * @param deviceSerial 设备序列号
     * @return EZDeviceUpgradeStatus对象
     */
    public EZDeviceUpgradeStatus getDeviceUpgradeStatus(String deviceSerial) throws BaseException {
        return mEzvizAPI.getDeviceUpgradeStatus(deviceSerial);
    }

    /**
     * 打开修改密码页面
     */
    public void openChangePasswordPage() {
        mEzvizAPI.openChangePasswordPage();
    }

    /**
     * 开始WiFi配置
     *
     * @param context      应用 activity context
     * @param deviceSerial 配置设备序列号
     * @param ssid         连接WiFi SSID
     * @param password     连接  WiFi 密码
     * @param mode         配网的方式，EZWiFiConfigMode中列举的模式进行任意组合,例如:EZWiFiConfigMode.EZWiFiConfigSmart|EZWiFiConfigMode
     *                     .EZWiFiConfigWave
     * @param back         配置回调
     * @since 4.3.0
     */
    public void startConfigWifi(Context context, String deviceSerial, String ssid, String password, int mode,
                                EZOpenSDKListener.EZStartConfigWifiCallback back) {
        mEzvizAPI.startConfigWifi(context, deviceSerial, ssid, password, mode,null, back);
    }

    /**
     * 开始WiFi配置
     *
     * @param context  应用 activity context
     * @param ssid     连接WiFi SSID
     * @param password 连接WiFi 密码
     * @param l        回调，用于处理连接设备的WiFi配置状态
     * @return 返回值并没有特别的含义，根据回调判断是否配置wifi成功
     * @deprecated
     */
    @Deprecated
    public boolean startConfigWifi(Context context, String ssid, String password, DeviceDiscoveryListener l) {
        return mEzvizAPI.startConfigWifi(context, ssid, password, l);
    }

    /**
     * 停止Wifi配置
     *
     * @return true 表示成功， false 表示失败
     */
    public boolean stopConfigWiFi() {
        return mEzvizAPI.stopConfigWiFi();
    }

    /**
     * AP配网接口,默认为"EZVIZ_"+设备序列号,设备AP热点密码默认为"EZVIZ_"+设备验证码,默认自动连接设备热点，需要获取可扫描wifi的权限
     *
     * @param ssid             WiFi的ssid
     * @param password         WiFi的密码
     * @param deviceSerial     设备序列号
     * @param verifyCode       设备验证码
     * @param apConfigCallback 结果回调
     */
    public void startAPConfigWifiWithSsid(final String ssid, final String password, String deviceSerial,
                                          final String verifyCode,
                                          final APWifiConfig.APConfigCallback apConfigCallback) {
        mEzvizAPI.startAPConfigWifiWithSsid(ssid, password, deviceSerial, verifyCode, apConfigCallback);
    }


    /**
     * AP配网接口
     *
     * @param ssid                       WiFi的ssid
     * @param password                   WiFi的密码
     * @param deviceSerial               设备序列号
     * @param verifyCode                 设备验证码
     * @param routerNamePre              设备热点名称，可传空，默认为"EZVIZ_"+设备序列号
     * @param routerPasswordPre          设备热点密码,可传空，默认为"EZVIZ_"+设备验证码
     * @param isAutoConnectDeviceHotSpot 是否自动连接设备热点,需要获取可扫描wifi的权限
     * @param apConfigCallback           结果回调
     */
    public void startAPConfigWifiWithSsid(final String ssid, final String password, String deviceSerial,
                                          final String verifyCode, final String routerNamePre,
                                          final String routerPasswordPre, boolean isAutoConnectDeviceHotSpot,
                                          final APWifiConfig.APConfigCallback apConfigCallback) {
        mEzvizAPI.startAPConfigWifiWithSsid(ssid, password, deviceSerial, verifyCode, routerNamePre,
                routerPasswordPre, isAutoConnectDeviceHotSpot, apConfigCallback);
    }

    /**
     * AP配网接口，如果你的设备热点是EZVIZ_开头的，deviceHotspotName和deviceHotspotPwd可传空；如果不是，这两个参数一定要传入对应的设备热点名和设备热点密码，否则配网失败
     *
     * @param wifiSsid                   WiFi的ssid
     * @param wifiPwd                    WiFi的密码
     * @param deviceSerial               设备序列号
     * @param deviceVerifyCode           设备验证码
     * @param deviceHotspotName          设备热点名称，可传空，默认为"EZVIZ_"+设备序列号
     * @param deviceHotspotPwd           设备热点密码,可传空，默认为"EZVIZ_"+设备验证码
     * @param autoConnectToDeviceHotSpot 是否自动连接设备热点,需要获取可扫描wifi的权限
     * @param apiUrl                     指定去哪个平台查询
     * @param callback                   结果回调
     */
    public void startAPConfigWifiWithSsid(final String wifiSsid, final String wifiPwd, String deviceSerial,
                                          final String deviceVerifyCode, final String deviceHotspotName,
                                          final String deviceHotspotPwd, boolean autoConnectToDeviceHotSpot,
                                          final String apiUrl, final APWifiConfig.APConfigCallback callback) {
        mEzvizAPI.startAPConfigWifiWithSsid(wifiSsid, wifiPwd, deviceSerial, deviceVerifyCode, deviceHotspotName, deviceHotspotPwd, autoConnectToDeviceHotSpot, apiUrl, callback);
    }


    /**
     * 停止AP配网
     */
    public void stopAPConfigWifiWithSsid() {
        mEzvizAPI.stopAPConfigWifiWithSsid();
    }

    // ------------------------------ 接触式配网 New AP Config ------------------------------

    /**
     * 获取接触式AP配网token
     *
     * @param callback
     */
    public void getNewApConfigToken(GetTokenCallback callback) {
        mEzvizAPI.getNewApConfigToken(callback);
    }

    /**
     * 设备配网（向设备发送wifi信息）
     *
     * @param token 通过getNewApConfigToken接口获取的token
     * @param ssid wifi名称
     * @param password wifi密码
     * @param lbsDomain 通过requestConfigToken接口获取的注册地址
     * @param callback
     */
    public void startNewApConfigWithToken(String token, String ssid, String password, String lbsDomain, StartNewApConfigCallback callback) {
        mEzvizAPI.startNewApConfigWithToken(token, ssid, password, lbsDomain, callback);
    }

    /**
     * 获取设备信息（需连接设备热点）
     *
     * @param callback
     */
    public void getAccessDeviceInfo(GetAccessDeviceInfoCallback callback){
        mEzvizAPI.getAccessDeviceInfo(callback);
    }

    /**
     * 获取设备环境wifi列表（需连接设备热点）
     *
     * @param callback
     */
    public void getAccessDeviceWifiList(GetDeviceWifiListCallback callback){
        mEzvizAPI.getAccessDeviceWifiList(callback);
    }

    /**
     * 查询设备绑定状态
     *
     * @param deviceSerial 设备序列号
     * @param callback
     */
    public void queryPlatformBindStatus(String deviceSerial, QueryPlatformBindStatusCallback callback) {
        mEzvizAPI.queryPlatformBindStatus(deviceSerial, callback);
    }

    /**
     * 设置配网设备网关地址 可选
     *
     * @param devRouteDomain 设备网关地址
     */
    public void setDevRouteDomain(String devRouteDomain) {
        mEzvizAPI.setDevRouteDomain(devRouteDomain);
    }

    /**
     * AP-Http配网接口
     * @param configToken                配网token
     * @param ssid                       WiFi的ssid
     * @param password                   WiFi的密码
     * @param routerName                 设备热点名称
     * @param routerPassword             设备热点密码
     * @param lbsDomain                  设备注册平台
     * @param isAutoConnectDeviceHotSpot 是否自动连接设备热点,需要获取可扫描wifi的权限
     * @param apConfigCallback           结果回调
     */
    public void startAPHttpConfigWifiWithToken(final String configToken, final String ssid, final String password,
                                               final String routerName, final String routerPassword, final String lbsDomain,
                                               boolean isAutoConnectDeviceHotSpot, APWifiConfig.APConfigCallback apConfigCallback) {
        mEzvizAPI.startAPHttpConfigWifiWithToken(configToken, ssid, password, routerName,
                routerPassword, lbsDomain, isAutoConnectDeviceHotSpot, apConfigCallback);
    }

    /**
     * 停止AP-Http配网
     */
    public void stopAPHttpConfigWifiWithToken() {
        mEzvizAPI.stopAPHttpConfigWifiWithToken();
    }

    /**
     * 根据视频广场url构造EZPlayer对象，用于视频广场的视频播放
     *
     * @param url 广场视频url
     * @return EZPlayer对象
     */
    public EZPlayer createPlayerWithUrl(final String url) {
        return mEzvizAPI.createPlayerWithUrl(url);
    }

    /**
     * 创建局域网播放器
     *
     * @param userId     设备登录成功后的userId
     * @param cameraNo   设备预览的通道号
     * @param streamType 设备预览的码流类型 1:主码流;2:子码流
     * @return
     */
    public EZPlayer createPlayerWithUserId(int userId, int cameraNo, int streamType) {
        return mEzvizAPI.createPlayerWithUserId(userId, cameraNo, streamType);
    }

    /**
     * 根据deviceSerial 和 cameraNo 构造EZPlayer对象
     *
     * @param deviceSerial
     * @param cameraNo
     * @return EZPlayer对象
     */
    public EZPlayer createPlayer(final String deviceSerial, int cameraNo) {
        return mEzvizAPI.createPlayer(deviceSerial, cameraNo);
    }

    /**
     * 根据deviceSerial 和 cameraNo 和 useSubStream构造EZPlayer对象
     * 一个页面存在多个视频使用最小的码流，没有子码流的话还是使用主码流
     *
     * @param deviceSerial 设备序列号
     * @param cameraNo     通道号
     * @param useSubStream 是否使用子码流
     * @return EZPlayer对象
     * @since V4.19.2
     */
    public EZPlayer createPlayer(final String deviceSerial, int cameraNo, boolean useSubStream) {
        return mEzvizAPI.createPlayerWithDeviceSerial(deviceSerial, cameraNo, useSubStream);
    }

    /**
     * 释放  EZPlayer 对象
     *
     * @param player 将要释放的EZPlayer对象
     */
    public void releasePlayer(EZPlayer player) {
        mEzvizAPI.releasePlayer(player);
    }

    /**
     * 获取好友分享的设备列表，返回EZDeviceInfo的对象数组
     * 该接口为耗时操作，建议放在线程中调用
     *
     * @param pageIndex 分页起始页，从0开始
     * @param pageSize  分页每页数量（建议20以内）
     * @return
     * @throws BaseException
     * @since 4.2
     */
    public List<EZDeviceInfo> getSharedDeviceList(int pageIndex, int pageSize) throws BaseException {
        return mEzvizAPI.getSharedDeviceList(pageIndex, pageSize);
    }

    /**
     * 设置指定监控点视频清晰度
     * 接口中有网络操作，需要在线程中调用
     *
     * @param deviceSerial 设备序列号
     * @param cameraNo     设备通道号，默认为1
     * @param videoLevel   清晰度 0-流畅 1-均衡 2-高品质
     * @return
     * @throws BaseException
     */
    public boolean setVideoLevel(String deviceSerial, int cameraNo, int videoLevel) throws BaseException {
        return mEzvizAPI.setDeviceVideoLevel(deviceSerial, cameraNo, videoLevel);
    }

    /**
     * 获取单个设备信息
     * 该接口为耗时操作，建议放在线程中调用
     *
     * @param deviceSerial 设备序列号
     * @return 设备信息对象EZDeviceInfo，与getDeviceList中对象一致
     * @throws BaseException
     * @since 4.3
     */
    public EZDeviceInfo getDeviceInfo(String deviceSerial) throws BaseException {
        return mEzvizAPI.getDeviceInfo(deviceSerial, false);
    }

    /**
     * 获取终端（手机等）唯一识别码
     *
     * @return 终端唯一识别码
     * @since 4.3.0
     */
    public String getTerminalId() {
        return mEzvizAPI.getTerminalId();
    }

//    /**
//     * 配置hiddns信息
//     * 该接口为耗时操作，建议放在线程中调用
//     *
//     * @param deviceSerial 序列号
//     * @param domain    设备域名,设备域名规则修改，不能为空，6-32位，可以为本身序列号，包含小写字母、数字、-，首位必须字母，末位不能为-
//     * @param upnp      upnp状态，1-手动，0-自动
//     * @param cmdPort   cmd端口
//     * @param httpPort  http端口
//     * @return
//     * @throws BaseException
//     * @since 4.3
//     */
//    public boolean deviceHiddnsConfigWithSerial(final String deviceSerial, final String domain, final int upnp,
//    final int cmdPort, final int httpPort ) throws BaseException {
//        return mEzvizAPI.deviceHiddnsConfigWithSerial(deviceSerial,domain,upnp,cmdPort,httpPort);
//    }

    /**
     * 清除取流时的缓存数据
     *
     * @since 4.5.0
     */
    public void clearStreamInfoCache() {
        mEzvizAPI.clearStreamInfoCache();
    }


    /**
     * 获取设备DDNS信息
     * 该接口为耗时操作，建议放在线程中调用
     * 设备序列号，deviceSerial和domain不能全为空，
     * 如果deviceSerial和domain都不为空，优先查询deviceSerial设备的ddns信息
     *
     * @param deviceSerial 设备序列号
     * @param domain       设备域名
     * @throws BaseException
     */

    public EZHiddnsDeviceInfo getDDNSWithDeviceSerial(final String deviceSerial, final String domain) throws BaseException {
        return mEzvizAPI.getDDNSWithDeviceSerial(deviceSerial, domain);
    }

    /**
     * 设置设备DDNS域名
     * 该接口为耗时操作，建议放在线程中调用
     * 设备序列号，deviceSerial和domain不能为空，
     *
     * @param deviceSerial 设备序列号
     * @param domain       设备域名,设备域名规则修改，不能为空，6-32位，可以为本身序列号，包含小写字母、数字、-，首位必须字母，末位不能为-
     * @throws BaseException
     */
    public void setDeviceDoamin(final String deviceSerial, final String domain) throws BaseException {
        mEzvizAPI.setDeviceDoamin(deviceSerial, domain);
    }

    /**
     * 设置设备DDNS自动映射
     * 该接口为耗时操作，建议放在线程中调用
     *
     * @param deviceSerial 设备序列号
     * @throws BaseException
     */

    public void setDDNSAutomatic(final String deviceSerial) throws BaseException {
        mEzvizAPI.setDDNSAutomatic(deviceSerial);
    }

    /**
     * 设置设备DDNS手动映射
     * 该接口为耗时操作，建议放在线程中调用
     *
     * @param deviceSerial 设备序列号
     * @param cmdPort      cmd（服务）端口
     * @param httpPort     http端口
     * @throws BaseException
     */
    public void setDDNSManual(final String deviceSerial, final int cmdPort, final int httpPort) throws BaseException {
        mEzvizAPI.setDDNSManual(deviceSerial, cmdPort, httpPort);
    }

    /**
     * 获取账户下所有设备列表DDNS信息
     * 该接口为耗时操作，建议放在线程中调用
     *
     * @param pageSize  分页大小，默认为10，最大为50
     * @param pageStart 分页起始页，从0开始，默认为0
     * @throws BaseException
     */
    public List<EZHiddnsDeviceInfo> getDDNSDeviceList(final int pageSize, final int pageStart) throws BaseException {
        return mEzvizAPI.getDDNSDeviceList(pageSize, pageStart);
    }


    /**
     * 分享设备DDNS信息,把单个设备的DDNS信息分享给其他账户
     * 该接口为耗时操作，建议放在线程中调用
     *
     * @param deviceSerial 设备序列号
     * @param account      被分享账户，可以是邮箱地址或手机号码（包含国家代码）或不是全数字的用户名
     * @throws BaseException
     */
    public void ShareDDNSDeviceList(final String deviceSerial, final String account) throws BaseException {
        mEzvizAPI.shareDDNSDeviceList(deviceSerial, account);
    }

    /**
     * 获取当前账号下的所有的其它账户分享给自己的设备DDNS信息
     * 该接口为耗时操作，建议放在线程中调用
     *
     * @param pageSize  分页大小，默认为10，最大为50
     * @param pageStart 分页起始页，从0开始，默认为0
     * @throws BaseException
     */
    public List<EZHiddnsDeviceInfo> getShareDDNSDeviceList(final int pageSize, final int pageStart) throws BaseException {
        return mEzvizAPI.getShareDDNSDeviceList(pageSize, pageStart);
    }

    /**
     * 是否已登录授权
     *
     * @since 4.8.3
     */
    public boolean isLogin() {

        return EZAuthApi.isLogin();
    }

    /**
     * 设置登录页的v参数，用于控制登录页样式
     *
     * @param vParam 登录页样式（mobile-移动版、wap-pc版。。。）
     * @since 4.8.7
     */
    public void setVparamForLoginPage(String vParam) {
        mEzvizAPI.setVparamForLoginPage(vParam);
    }

    /**
     * 切换到指定服务区域
     *
     * @param apiUrl 区域接口请求域名
     * @param webUrl 区域WEB登录域名（默认可不填写）
     * @since 4.11.0
     */
    public void setServerUrl(String apiUrl, String webUrl) {
        mEzvizAPI.setServerUrl(apiUrl, webUrl);
    }

    /**
     * 检查国家是否支持云存储服务，只支持海外
     * 该接口为耗时操作，建议放在线程中调用
     *
     * @throws BaseException
     * @since 4.19.4
     */
    public boolean isSupportCloundService() throws BaseException {
        return mEzvizAPI.isSupportCloundService();
    }

    /**
     * 查询云存储设备通道套餐信息
     * 该接口为耗时操作，建议放在线程中调用
     *
     * @param deviceSerial 设备序列号
     * @param cameraNo     默认为1
     * @throws BaseException
     * @since 4.19.4
     */
    public EZDeviceCloudServiceInfo getCloundDevicePackageInfo(final String deviceSerial, final int cameraNo) throws BaseException {
        return mEzvizAPI.getCloundDevicePackageInfo(deviceSerial, cameraNo);
    }

    /**
     * 云存储功能暂停恢复
     *
     * @param deviceSerial 设备序列号
     * @param cameraNo     默认为1
     * @param enable       false-禁用，true-启用
     * @throws BaseException
     * @since 4.19.4
     */
    public boolean setCloundServiceActive(final String deviceSerial, final int cameraNo, final boolean enable) throws BaseException {
        return mEzvizAPI.setCloundServiceActive(deviceSerial, cameraNo, enable);
    }

    /**
     * 查询某月中有视频文件的天(日期)
     *
     * @param deviceSerial 设备序列号
     * @param cameraNo     默认为1
     * @param month        查询某月具有云存储的日期，格式为yyyyMM
     * @throws BaseException
     * @since 4.19.4
     */
    public List<String> getCloudVideoDays(final String deviceSerial, final int cameraNo, final String month) throws BaseException {
        return mEzvizAPI.getCloudVideoDays(deviceSerial, cameraNo, month);
    }

    /**
     * 按设备通道删除所有云存储录像片段
     *
     * @param deviceSerial 设备序列号
     * @param cameraNo     默认为1
     * @throws BaseException
     * @since 4.19.4
     */
    public boolean deleteAllCloudVideo(final String deviceSerial, final int cameraNo) throws BaseException {
        return mEzvizAPI.deleteAllCloudVideo(deviceSerial, cameraNo);
    }

    /**
     * 按天增量查询云存储录像列表接口(概要信息)
     *
     * @param deviceSerial  设备序列号
     * @param cameraNo      默认为1
     * @param videoType     录像类型videoType
     * @param searchDate    查找文件日期yyyy-MM-dd
     * @param maxCreateTime 查找文件的起始时间yyyy-MM-dd HH:mm:ss，要保证和searchDate是同一天，否则报错。默认从 yyyy-MM-dd 00:00:00开始，非必填，可传null
     * @throws BaseException
     * @since 4.19.4
     */
    public List<String> getIncrCloudVideos(final String deviceSerial, final int cameraNo,
                                           final EZConstants.EZCloudVideoType videoType, final String searchDate,
                                           final String maxCreateTime) throws BaseException {
        return mEzvizAPI.getIncrCloudVideos(deviceSerial, cameraNo, videoType, searchDate, maxCreateTime);
    }

    /**
     * 根据文件id批量查询详情信息接口
     *
     * @param deviceSerial 设备序列号
     * @param cameraNo     默认为1
     * @param videos       视频数组（限制30个以内）
     * @throws BaseException
     * @since 4.19.4
     */
    public List<EZCloudRecordFile> getCloudVideoDetails(final String deviceSerial, final int cameraNo,
                                                        final List<String> videos) throws BaseException {
        return mEzvizAPI.getCloudVideoDetails(deviceSerial, cameraNo, videos);
    }

    /**
     * 删除云存储录像片段
     *
     * @param deviceSerial 设备序列号
     * @param cameraNo     默认为1
     * @param videos       视频数组（限制30个以内）
     * @throws BaseException
     * @since 4.19.4
     */
    public boolean deleteCloudVideoFragment(final String deviceSerial, final int cameraNo, final List<String> videos) throws BaseException {
        return mEzvizAPI.deleteCloudVideoFragment(deviceSerial, cameraNo, videos);
    }

}
