package net.northking.cctp.upperComputer.webSocket.thread;

import com.alibaba.fastjson.JSON;
import net.northking.cctp.upperComputer.constants.RequestCmd;
import net.northking.cctp.upperComputer.exception.ParamMistakeException;
import net.northking.cctp.upperComputer.utils.SessionUtils;
import net.northking.cctp.upperComputer.webSocket.entity.CatchParam;
import net.northking.cctp.upperComputer.webSocket.entity.CmdRequest;
import net.northking.cctp.upperComputer.webSocket.entity.ParamCheck;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import javax.websocket.Session;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;

public abstract class AbstractMessageHandler extends Thread implements MessageHandler{

    private final Logger logger = LoggerFactory.getLogger(AbstractMessageHandler.class);
    //消息
    protected BlockingDeque<CmdRequest> cmdQueues = new LinkedBlockingDeque<>();

    //发送消息到后端的session
    protected Session session;

    protected String serial;

    protected CatchParam catchParam = new CatchParam();

    protected NotifyWebCloseConnectionThread notifyWebCloseConnectionThread;

    @Override
    public void addQueue(CmdRequest request) {
        cmdQueues.add(request);
    }

    @Override
    public void startHandMessage() {
        logger.debug("设备【{}】开始处理前端指令..........",serial);
        this.start();
    }

    @Override
    public void run() {
        while (!isInterrupted()) {
            CmdRequest request = null;
            try {
                request = cmdQueues.take();
            } catch (InterruptedException e) {
                break;
            }
            try {
                if (RequestCmd.SCREEN_ON.equals(request.getCmd())) {  //开启投屏
                    handleScreenOn(request);
                } else if (RequestCmd.SCREEN_SIZE.equals(request.getCmd())) {  //改变屏幕大小
                    changeScreenSize(request);
                } else if (RequestCmd.SCREEN_QUALITY.equals(request.getCmd())) { //改变屏幕质量
                    changeScreenQuality(request);
                } else if (RequestCmd.SCREEN_RECORD_ON.equals(request.getCmd())) {//开启录屏
                    startRecordScreen(request);
                } else if (RequestCmd.SCREEN_RECORD_OFF.equals(request.getCmd())) { //结束录屏
                    stopRecordScreen(request);
                } else if (RequestCmd.SCREEN_CAPTURE.equals(request.getCmd())) {//截图
                    screenShot(request);
                } else if (RequestCmd.INPUT_TOUCH_DOWN.equals(request.getCmd())) { //鼠标摁下
                    touchDown(request);
                } else if (RequestCmd.INPUT_TOUCH_MOVE.equals(request.getCmd())) {  //鼠标滑动
                    touchMove(request);
                } else if (RequestCmd.INPUT_TOUCH_UP.equals(request.getCmd())) { //鼠标抬起
                    touchUp(request);
                } else if (RequestCmd.INPUT_KEY_PRESS.equals(request.getCmd())) {  //发送热键
                    inputKeyPress(request);
                } else if (RequestCmd.INPUT_KEY_DOWN.equals(request.getCmd())) { //键盘按下
                    inputKeyDown(request);
                } else if (RequestCmd.INPUT_KEY_UP.equals(request.getCmd())) { //键盘抬起
                    inputKeyUp(request);
                } else if (RequestCmd.INPUT_TYPE.equals(request.getCmd())) { //键盘输入
                    inputType(request);
                } else if (RequestCmd.INPUT_SET_TEXT.equals(request.getCmd())) {  //设置输入文本
                    inputSetText(request);
                } else if (RequestCmd.CLIPBOARD_PAST.equals(request.getCmd())) {  //设置手机剪贴板内容
                    clipboardPast(request);
                } else if (RequestCmd.CLIPBOARD_COPY.equals(request.getCmd())) {  //获取手机剪贴板内容
                    clipboardCopy(request);
                } else if (RequestCmd.DEVICE_ROTATE.equals(request.getCmd())) {  //旋转屏幕
                    rotationScreen(request);
                } else if (RequestCmd.DEVICE_REBOOT.equals(request.getCmd())) {  //重启手机
                    restartDevice(request);
                } else if (RequestCmd.DEVICE_SHUTDOWN.equals(request.getCmd())) { //关机

                } else if (RequestCmd.DEVICE_START_NODE.equals(request.getCmd())) { //开始获取node节点数据
                    startUiNode(request);
                } else if (RequestCmd.DEVICE_STOP_NODE.equals(request.getCmd())) {  //停止获取node节点数据
                    stopUiNode(request);
                } else if (RequestCmd.DEVICE_OPEN_SETTING.equals(request.getCmd())) { //打开设置
                    openSetting(request);
                } else if (RequestCmd.DEVICE_OPEN_CAMERA.equals(request.getCmd())) { //打开相机
                    deviceOpenCamera(request);
                } else if (RequestCmd.DEVICE_APP_LIST.equals(request.getCmd())) { //获取应用列表
                    getAppList(request);
                } else if (RequestCmd.DEVICE_INSTALL.equals(request.getCmd())) {  //安装应用
                    installApp(request);
                } else if (RequestCmd.DEVICE_UNINSTALL.equals(request.getCmd())) {//卸载应用
                    uninstallApp(request);
                } else if (RequestCmd.DEVICE_WIFI.equals(request.getCmd())) { //设置wifi
                    setWifiStatus(request);
                } else if (RequestCmd.DEVICE_OPEN_BROWSER.equals(request.getCmd())) { //打开浏览器
                    openBrowser(request);
                } else if (RequestCmd.SHELL_COMMAND.equals(request.getCmd())) { //发送shell命令
                    sendShellToDevice(request);
                } else if (RequestCmd.LOGCAT_START.equals(request.getCmd())) { //开启日志
                    startLogcat(request);
                } else if (RequestCmd.LOGCAT_STOP.equals(request.getCmd())) { //停止获取日志
                    stopLogcat(request);
//                } else if (RequestCmd.LOGCAT_DOWNLOAD.equals(request.getCmd())) { //日志下载
//                    downloadLogcat(request);
                } else if (RequestCmd.FS_LIST.equals(request.getCmd())) { //获取文件列表
                    getFileList(request);
                } else if (RequestCmd.FS_PUSH.equals(request.getCmd())) { //上传文件
                    pushFileToDevice(request);
                } else if (RequestCmd.FS_PULL.equals(request.getCmd())) { //下载手机文件
                    pullFileFromDevice(request);
                } else if (RequestCmd.CONNECT_START.equals(request.getCmd())) { //打开远程adb调试
                    openADBDebug(request);
                } else if (RequestCmd.CONNECT_STOP.equals(request.getCmd())) { //关闭adb调试
                    closeADBDebug(request);
                } else if (RequestCmd.PERF_START.equals(request.getCmd())) { //开启性能获取
                    startPerf(request);
                } else if (RequestCmd.PERF_STOP.equals(request.getCmd())) { //关闭性能获取
                    stopPerf(request);
                } else {
                    logger.warn("未知指令：{}", request.getCmd());
                    SessionUtils.sendFailureMessage(session, request, "未知指令:" + request.getCmd());
                }
            } catch (Throwable throwable) {
                logger.debug("出现未知错误",throwable);
            }
        }
        logger.warn("设备【{}】处理消息线程退出",serial);
    }

    protected Map<String, Object> checkParam(Map<String, Object> data, boolean allowNull, ParamCheck... params) throws Exception {
        if (!allowNull) {
            if (null == data) {
                throw new ParamMistakeException("传递参数为空");
            }
        }
        Map<String, Object> paramMap = new HashMap<>();
        if (null != data) {
            for (ParamCheck paramCheck : params) {
                String type = paramCheck.getType();
                Object value = data.get(paramCheck.getName());
                if (paramCheck.isRequire()) {
                    if (null == value) {
                        throw new ParamMistakeException(String.format("参数[%s]得值不能为空", paramCheck.getName()));
                    }
                }
                if (null != value) {
                    if ("string".equals(type)) {
                        String valueStr = value + "";
                        boolean checkSize = paramCheck.isCheckSize();
                        if (checkSize) {  //验证长度
                            Integer length = paramCheck.getLength();
                            if (null != length && length > 0) {
                                if (valueStr.length() > length) {
                                    throw new ParamMistakeException(String.format("参数[%s]的值过长", paramCheck.getName()));
                                }
                            }
                        } else {
                            List<String> stringValue = paramCheck.getStringValue();
                            if (!CollectionUtils.isEmpty(stringValue) && !stringValue.contains(valueStr)) {
                                throw new ParamMistakeException(String.format("参数[%s]的值应该在%s中选择", paramCheck.getName(), JSON.toJSONString(stringValue)));
                            }
                        }
                        paramMap.put(paramCheck.getName(), valueStr);
                    } else if ("int".equals(type)) {
                        Integer valueInt = 0;
                        try {
                            valueInt = Integer.parseInt(value + "");
                        } catch (NumberFormatException e) {
                            throw new ParamMistakeException(String.format("参数[%s]的值需要整数，值[%s]无法转换为整数", paramCheck.getName(), value));
                        }
                        if (paramCheck.isCheckSize()) {  //检查大小
                            if (null != paramCheck.getMin()) {
                                if (valueInt < paramCheck.getMin()) {
                                    throw new ParamMistakeException(String.format("参数[%s]的值过小，值不能小于[%s]", paramCheck.getName(), paramCheck.getMin()));
                                }
                            }
                            if (null != paramCheck.getMax()) {
                                if (valueInt > paramCheck.getMax()) {
                                    throw new ParamMistakeException(String.format("参数[%s]的值过大，值不能大于[%s]", paramCheck.getName(), paramCheck.getMax()));
                                }
                            }
                        } else {   //检查值是否在给定的数之间
                            List<Integer> intValue = paramCheck.getIntValue();
                            if (null != intValue && !intValue.contains(valueInt)) {
                                throw new ParamMistakeException(String.format("参数[%s]的值应该在%s之间", paramCheck.getName(), JSON.toJSONString(intValue)));
                            }
                        }
                        paramMap.put(paramCheck.getName(), valueInt);
                    } else if ("boolean".equals(type)) {
                        String booleanValue = value + "";
                        if ("true".equals(booleanValue)) {
                            paramMap.put(paramCheck.getName(), true);
                        } else if ("false".equals(booleanValue)) {
                            paramMap.put(paramCheck.getName(), false);
                        } else {
                            throw new ParamMistakeException(String.format("参数[%s]的值需要布尔，值[%s]无法转换为布尔", paramCheck.getName(), value));
                        }
                    } else if ("double".equals(type)) {
                        Double doubleValue;
                        try {
                            doubleValue = Double.parseDouble(value + "");
                        } catch (NumberFormatException e) {
                            throw new ParamMistakeException(String.format("参数[%s]的值需要double，值[%s]无法转换为double", paramCheck.getName(), value));
                        }
                        if (paramCheck.isCheckSize()) {  //检查大小
                            if (null != paramCheck.getMin()) {
                                if (doubleValue < paramCheck.getMin()) {
                                    throw new ParamMistakeException(String.format("参数[%s]的值过小，值不能小于[%s]", paramCheck.getName(), paramCheck.getMin()));
                                }
                            }
                            if (null != paramCheck.getMax()) {
                                if (doubleValue > paramCheck.getMax()) {
                                    throw new ParamMistakeException(String.format("参数[%s]的值过大，值不能大于[%s]", paramCheck.getName(), paramCheck.getMax()));
                                }
                            }
                        }
                        paramMap.put(paramCheck.getName(), doubleValue);
                    } else if ("float".equals(type)) {
                        Float floatValue;
                        try {
                            floatValue = Float.parseFloat(value + "");
                        } catch (NumberFormatException e) {
                            throw new ParamMistakeException(String.format("参数[%s]的值需要float，值[%s]无法转换为float", paramCheck.getName(), value));
                        }
                        if (paramCheck.isCheckSize()) {  //检查大小
                            if (null != paramCheck.getMin()) {
                                if (floatValue < paramCheck.getMin()) {
                                    throw new ParamMistakeException(String.format("参数[%s]的值过小，值不能小于[%s]", paramCheck.getName(), paramCheck.getMin()));
                                }
                            }
                            if (null != paramCheck.getMax()) {
                                if (floatValue > paramCheck.getMax()) {
                                    throw new ParamMistakeException(String.format("参数[%s]的值过大，值不能大于[%s]", paramCheck.getName(), paramCheck.getMax()));
                                }
                            }
                        }
                        paramMap.put(paramCheck.getName(), floatValue);
                    }
                }


            }
        }
        return paramMap;
    }

    @Override
    public void notifyDeviceOfflineToWeb() {
        //通知前端设备现在处于掉线的状态,前端开始转圈
        if (null == notifyWebCloseConnectionThread) {
            notifyWebCloseConnectionThread = new NotifyWebCloseConnectionThread(session, serial);
            notifyWebCloseConnectionThread.start();
        } else {
            logger.debug("监控设备【{}】掉线的线程已经存在........................",serial);
        }
    }

    @Override
    public void notifyDeviceOnlineToWeb() {
        //通知前端设备现在处于掉线的状态,前端开始转圈
        if (null != notifyWebCloseConnectionThread && notifyWebCloseConnectionThread.isAlive() && !notifyWebCloseConnectionThread.isInterrupted()) {
            notifyWebCloseConnectionThread.cancelNotifyWebDisconnect();
        }
        notifyWebCloseConnectionThread = null;
    }
}
