package com.sensetime.demo;

import android.text.TextUtils;
import android.util.Log;

import com.blankj.utilcode.util.LogUtils;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.sensetime.mtc.AiConfig;
import com.sensetime.mtc.MClient;
import com.sensetime.mtc.MtcCode;

import java.io.File;


/**
 * Author:Created by LaoTie on 2019/12/12.
 * Enterprise:SenseTime
 **/
public class SenseTimeMtc {
    public static final String TAG = "SenseTimeMtc";

    public static final int M20 = 20;
    public static final int M20S = 21;
    public static final int M10 = 10;
    public static final int M30 = 30;
    public static final int UNKNOWN_DEVICE_MODULE = 0;

    public static final int LANDSCAPE_0 = 0x01; // 横屏0度
    public static final int PORTRAIT_90 = 0x02;// 竖屏90度
    public static final int LANDSCAPE_180 = 0x03; // 横屏180度
    public static final int PORTRAIT_270 = 0x04;// 竖屏270度

    public static final int TURN_OFF_AUTO_UPLOAD_AI_INFO = 0x01;// 关闭主动上报的功能
    public static final int TURN_ON_AUTO_UPLOAD_PICTURE_RECO = 0x02;// 打开主动上报的功能，且只上报图片与识别数据
    public static final int TURN_ON_AUTO_UPLOAD_FEATURE_RECO = 0x03;// 打开主动上报的功能，且只上报特征值与识别数据
    public static final int TURN_ON_AUTO_UPLOAD_RECO = 0x04;// 打开主动上报的功能，且只上报识别数据

    public static final int TURN_ON_FRAME_CARRIES_AI_INFO = 0x00;// 打开视频帧携带人脸识别数据的功能
    public static final int TURN_OFF_FRAME_CARRIES_AI_INFO = 0x01;// 关闭视频帧携带人脸识别数据的功能

    private final String devNamePrefix = "/dev/ttyACM";
    private int mDeviceModule = UNKNOWN_DEVICE_MODULE;
    private boolean isInitSuccess = false;
    private int mCameraWidth = 1280;
    private int mCameraHeight = 720;
    private boolean mScaleHeight = false;
    private int mM10_L_P = PORTRAIT_90;   //1: 1280x720 ,  2: 720x1280;

    private int autoUploadAiInfoMode = TURN_ON_AUTO_UPLOAD_RECO;
    private int frameCarriesAiInfoMode = TURN_OFF_FRAME_CARRIES_AI_INFO;

    private int enableQrCode = 0;
    private int recQrCodeIntervalTime = 5;

    private boolean rgbFaceImg = true;
    private boolean rgbBgImg = true;
    private boolean irImg = true;


    private boolean isPauseAI = false;

    private int mPreviewWidth = 1280;
    private int mPreviewHeight = 720;

    /**
     * 分辨率,720p和360p，默认0x00 是720p
     */
    private int screenSize = 0x00;

    /**
     * 模组自带AE RGB摄像头的抗闪是否打开 0x00代表关闭（去使能），0x01代表打开（使能）
     */
    private int deviceAntiFlickerEnabledRGB = 0x00;

    /**
     * 模组自带AE IR摄像头的抗闪是否打开 0x00代表关闭（去使能），0x01代表打开（使能）
     */
    private int deviceAntiFlickerEnabledIR = 0x00;

    /**
     * 模组自带RGB 抗闪频率，0x00代表50HZ，0x01 代表60HZ
     */
    private int deviceAntiFlickerFrequencyRGB = 0x00;

    /**
     * 模组自带IR抗闪频率，0x00代表50HZ，0x01 代表60HZ
     */
    private int deviceAntiFlickerFrequencyIR = 0x01;

    /**
     * 判断是否是IR模式
     */
    private int isIRRGBMode = IR_RGB_NONE;

    /**
     * 默认0x00 镜像模式
     */
    private int isMirror = 0x00;

    /**
     * RGB 摄像头状态
     */
    private int cameraStatusRGB;

    /**
     * IR 摄像头状态
     */
    private int cameraStatusIR;

    /**
     * 休眠模式
     */
    private int sleepMode = SYSTEM_NOT_SLEEP;   //非休眠模式

    public static final int CAMERA_OPEN = 1;
    public static final int CAMERA_CLOSE = 0;

    public final static int IR_RGB_NONE = -1;
    public final static int RGB = 0;
    public final static int IR = 1;

    public static final int SYETEM_SLEEP = 0;
    public static final int SYSTEM_NOT_SLEEP = 1;

    private MClient mClient;

    public interface InitCallback {

        void onFinish();
    }

    public static SenseTimeMtc getInstance() {
        return MtcHolder.senseTimeMtcInstance;
    }

    private SenseTimeMtc() {
        mClient = MClient.getInstance();
    }

    private static class MtcHolder {
        private static SenseTimeMtc senseTimeMtcInstance = new SenseTimeMtc();
    }

    public int getCameraWidth() {
        return mCameraWidth;
    }

    public void setCameraWidth(int v) {
        mCameraWidth = v;
    }

    public int getCameraHeight() {
        return mCameraHeight;
    }

    public void setCameraHeight(int v) {
        mCameraHeight = v;
    }

    public int getEnableQrCode() {
        return enableQrCode;
    }

    public void setEnableQrCode(int v) {
        enableQrCode = v;
    }

    public int getRecQrCodeIntervalTime() {
        return recQrCodeIntervalTime;
    }

    public void setRecQrCodeIntervalTime(int v) {
        recQrCodeIntervalTime = v;
    }

    public int getPreviewWidth() {
        return mPreviewWidth;
    }

    public void setPreviewWidth(int v) {
        mPreviewWidth = v;
    }

    public int getPreviewHeight() {
        return mPreviewHeight;
    }

    public void setPreviewHeight(int v) {
        mPreviewHeight = v;
    }

    public int getScreenSize() {
        return screenSize;
    }

    public void setScreenSize(int v) {
        screenSize = v;
    }

    public int getIsIRRGBMode() {
        return isIRRGBMode;
    }

    public void setIsIRRGBMode(int v) {
        isIRRGBMode = v;
    }

    public int getIsMirror() {
//        Log.d(TAG, "[getIsMirror] isMirror [" + isMirror + "]");
        return isMirror;
    }

    public void setIsMirror(int v) {
        Log.d(TAG, "[setIsMirror] v [" + v + "]");
        isMirror = v;
    }

    public int getCameraStatusRGB() {
        return cameraStatusRGB;
    }

    public void setCameraStatusRGB(int v) {
        cameraStatusRGB = v;
    }

    public int getCameraStatusIR() {
        return cameraStatusIR;
    }

    public void setCameraStatusIR(int v) {
        cameraStatusIR = v;
    }

    public int getSleepMode() {
        return sleepMode;
    }

    public void setSleepMode(int v) {
        sleepMode = v;
        if(sleepMode == SYETEM_SLEEP)
        {
            setCameraStatusRGB(CAMERA_CLOSE);
            setCameraStatusIR(CAMERA_CLOSE);
        }
        else
        {
            setCameraStatusRGB(CAMERA_OPEN);
            setCameraStatusIR(CAMERA_OPEN);
        }
    }

    public String getDevicePath() {
        int devNameIndex = 3;
        String dev = "";
        for (int i = 0; i <= devNameIndex; i++) {
            dev = devNamePrefix + i;
            File device = new File(dev);
            if (device.exists()) {
                if (!device.canRead() || !device.canWrite() || !device.canExecute()) {
                    LogUtils.eTag(TAG, "can't read/write device: " + dev + ", start get root permission.");
                } else {
                    LogUtils.vTag(TAG, dev + " is exists");
                    return dev;
                }
            } else {
                LogUtils.vTag(TAG, dev + " is't exists");
            }
        }
        return "";
    }

    public void initMtc(InitCallback initCallback) {
        isInitSuccess = false;
        mDeviceModule = UNKNOWN_DEVICE_MODULE;
        LogUtils.dTag(TAG, "init mtc");
        int fd = UsbDeviceHelper.getInstance().getFd();
        if (fd == Integer.MIN_VALUE) {
            initCallback.onFinish();
            return;
        }
        int busNum = UsbDeviceHelper.getInstance().getBusNum();
        int devNum = UsbDeviceHelper.getInstance().getDevNum();

        mClient.mtcInit(fd, busNum, devNum, (mtcCode, result) -> {
            if (mtcCode == MtcCode.SUCCESS || mtcCode == MtcCode.ERR_ALREADY_INIT) {
                isInitSuccess = true;
                getMTCInfo(initCallback);
            } else {
                initCallback.onFinish();
            }
        });
    }


    public void getMTCInfo(InitCallback initCallback) {
        LogUtils.dTag(TAG, "get device info.");
        mClient.mtcDeviceModuleGet((mtcCode, result) -> {
            if (mtcCode == MtcCode.SUCCESS && !TextUtils.isEmpty(result)) {
                Log.d(TAG, "[getMTCInfo] device module type result [" + result + "]");
                if (result.equals("M10")) {
                    mDeviceModule = M10;
                    mM10_L_P = LANDSCAPE_0;//M10默认横屏
                    mClient.mtcDeviceScreenModeGet((mtcCode1, result1) -> {
                        LogUtils.dTag(TAG, "mtcCode1:" + mtcCode1);
                        if (mtcCode1 == MtcCode.SUCCESS && !TextUtils.isEmpty(result1)) {
                            int mode = Integer.parseInt(result1);
                            LogUtils.dTag(TAG, "screen mode:" + mode);
                            setmM10_L_P(mode);
                        }

                        initCallback.onFinish();
                    });
                } else if (result.equals("SENM2HD02") || result.equals("SENM2HD12")) {
                    mDeviceModule = M20S;
                } else if (result.equals("SenseEngineM20") || result.equals("SensePassM20")) {
                    mDeviceModule = M20;
                } else if (result.equals("SenseEngine M30") || result.equals("SenseEngineM30")) {
                    mDeviceModule = M30;
                } else {
                    mDeviceModule = UNKNOWN_DEVICE_MODULE;
                    LogUtils.dTag(TAG, "Not find m10 or m20 or m30,unknow device.");
                }
                Log.d(TAG, "[getMTCInfo] ************* DEVICE_MODULETYPE ************* [" + mDeviceModule + "]");
            } else {
                LogUtils.eTag(TAG, "can't get deviceInfo");
            }
            initCallback.onFinish();
        });


        mClient.mtcAiConfigGet((mtcCode, result) -> {
            if (mtcCode == MtcCode.SUCCESS && !TextUtils.isEmpty(result)) {
                try {
                    Gson gson = new Gson();
                    LogUtils.dTag(TAG, "result:" + result);
                    AiConfig aiConfig = gson.fromJson(result, AiConfig.class);
                    if (aiConfig != null) {
                        AiConfig.setInstance(aiConfig);
                    }
                } catch (JsonSyntaxException e) {
                    LogUtils.eTag(TAG, e.getMessage());
                }
            }
        });


        mClient.mtcAiControlAutoUploadAiInfo(autoUploadAiInfoMode, rgbFaceImg, rgbBgImg, irImg, (mtcCode, result) ->
                LogUtils.dTag(TAG, "open mtcAiControlAutoUploadAiInfo's mtcCode:" + mtcCode));

        mClient.mtcUploadFrameAiInfo(frameCarriesAiInfoMode, (mtcCode, result) ->
                LogUtils.dTag(TAG, "mtcUploadFrameAiInfo's  mtcCode:" + mtcCode));

        if (mDeviceModule == M20S) {
            mClient.mtcSetQrCodeEnable(enableQrCode, recQrCodeIntervalTime, (mtcCode, result) -> LogUtils.dTag(TAG, "mtcSetQrCodeEnable's mtcCode:" + mtcCode.getRetCode() + ",  result:" + result));
        }

        int irRGBMode = RGB;
        if (isIRRGBMode != IR_RGB_NONE) {
            irRGBMode = isIRRGBMode;
        }
        mClient.mtcDeviceCameraSwitch(irRGBMode, isMirror, (mtcCode, result) -> LogUtils.dTag(TAG, "mtcDeviceCameraSwitch's mtcCode:" + mtcCode));

        MClient.getInstance().mtcDeviceCameraStatusGet(0x01, (mtcCode, result) -> {
            LogUtils.dTag(TAG, "result:" + result);
            if (mtcCode == MtcCode.SUCCESS && !TextUtils.isEmpty(result)) {
                cameraStatusIR = Integer.parseInt(result);
            }
        });
        MClient.getInstance().mtcDeviceCameraStatusGet(0x00, (mtcCode, result) -> {
            if (mtcCode == MtcCode.SUCCESS && !TextUtils.isEmpty(result)) {
                cameraStatusRGB = Integer.parseInt(result);
            }
        });
        // sdk初始化成功需要设置一遍屏幕分辨率
        mClient.mtcDeviceScreenSizeSet(SenseTimeMtc.getInstance().getScreenSize(), (mtcCode, result) -> {
            LogUtils.dTag(TAG, "mtcDeviceScreenSizeSet's  mtcCode:" + mtcCode);
        });
    }

    public boolean isRgbFaceImg() {
        return rgbFaceImg;
    }

    public void setRgbFaceImg(boolean rgbFaceImg) {
        this.rgbFaceImg = rgbFaceImg;
    }

    public boolean isRgbBgImg() {
        return rgbBgImg;
    }

    public void setRgbBgImg(boolean rgbBgImg) {
        this.rgbBgImg = rgbBgImg;
    }

    public boolean isIrImg() {
        return irImg;
    }

    public void setIrImg(boolean irImg) {
        this.irImg = irImg;
    }

    public boolean isInitSuccess() {
        return isInitSuccess;
    }

    public void setInitStatus(boolean isInit) {
        isInitSuccess = isInit;
    }

    public boolean ismScaleHeight() {
        return mScaleHeight;
    }

    public void setmScaleHeight(boolean mScaleHeight) {
        this.mScaleHeight = mScaleHeight;
    }

    public int getmM10_L_P() {
        return mM10_L_P;
    }

    public void setmM10_L_P(int mM10_L_P) {
        this.mM10_L_P = mM10_L_P;
    }


    public int getmDeviceModule() {
//        Log.d(TAG, "[getmDeviceModule] mDeviceModule [" + mDeviceModule + "]");
        return mDeviceModule;
    }

    public int getAutoUploadAiInfoMode() {
        return autoUploadAiInfoMode;
    }

    public void setAutoUploadAiInfoMode(int autoUploadAiInfoMode) {
        this.autoUploadAiInfoMode = autoUploadAiInfoMode;
    }

    public int getFrameCarriesAiInfoMode() {
        return frameCarriesAiInfoMode;
    }

    public void setFrameCarriesAiInfoMode(int frameCarriesAiInfoMode) {
        this.frameCarriesAiInfoMode = frameCarriesAiInfoMode;
    }

    public boolean isPauseAI() {
        return isPauseAI;
    }

    public void setPauseAI(boolean pauseAI) {
        isPauseAI = pauseAI;
    }

    public int getDeviceAntiFlickerEnabledRGB() {
        return deviceAntiFlickerEnabledRGB;
    }

    public void setDeviceAntiFlickerEnabledRGB(int deviceAntiFlickerEnabledRGB) {
        this.deviceAntiFlickerEnabledRGB = deviceAntiFlickerEnabledRGB;
    }

    public int getDeviceAntiFlickerEnabledIR() {
        return deviceAntiFlickerEnabledIR;
    }

    public void setDeviceAntiFlickerEnabledIR(int deviceAntiFlickerEnabledIR) {
        this.deviceAntiFlickerEnabledIR = deviceAntiFlickerEnabledIR;
    }

    public int getDeviceAntiFlickerFrequencyRGB() {
        return deviceAntiFlickerFrequencyRGB;
    }

    public void setDeviceAntiFlickerFrequencyRGB(int deviceAntiFlickerFrequencyRGB) {
        this.deviceAntiFlickerFrequencyRGB = deviceAntiFlickerFrequencyRGB;
    }

    public int getDeviceAntiFlickerFrequencyIR() {
        return deviceAntiFlickerFrequencyIR;
    }

    public void setDeviceAntiFlickerFrequencyIR(int deviceAntiFlickerFrequencyIR) {
        this.deviceAntiFlickerFrequencyIR = deviceAntiFlickerFrequencyIR;
    }

}
