package net.northking.cctp.upperComputer.deviceManager.screen;

import net.northking.cctp.upperComputer.constants.ResponseCmd;
import net.northking.cctp.upperComputer.deviceManager.AndroidDeviceManager;
import net.northking.cctp.upperComputer.driver.adb.AdbDevice;
import net.northking.cctp.upperComputer.driver.agent.AndroidAgentSession;
import net.northking.cctp.upperComputer.driver.agent.command.ScreenStreamCommand;
import net.northking.cctp.upperComputer.driver.agent.command.WatchScreenStreamCommand;
import net.northking.cctp.upperComputer.utils.SessionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import javax.websocket.Session;
import java.io.DataInput;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class AndroidScreenResponseThread extends ImageScreenResponse {

    private AndroidAgentSession asyncAgentSession;

    private AdbDevice adbDevice;

    private final Logger logger = LoggerFactory.getLogger(AndroidScreenResponseThread.class);

    public AndroidScreenResponseThread(AdbDevice adbDevice) {
        this.adbDevice = adbDevice;
        this.deviceId = adbDevice.getSerial();
        setName("[" + adbDevice.getSerial() + "-response]");
    }

    @Override
    public void run() {
        while (!isInterrupted()) {
            if (!CollectionUtils.isEmpty(webSessions)) {
                //通知前端开始连接
                Map<String, Object> messageMap = new HashMap<>();
                messageMap.put(ResponseCmd.DeviceStatus.STATUS, ResponseCmd.DeviceStatus.CONNECTING);
                for (Session webSession : webSessions) {
                    if (webSession.isOpen()) {
                        SessionUtils.sendMessageInitiative(webSession, ResponseCmd.DEVICE_STATUS, adbDevice.getSerial(), messageMap, "设备掉线了");
                    }
                }
            }
            AdbDevice currentDevice = AndroidDeviceManager.getInstance().getCurrentDevice(adbDevice.getSerial());
            if (null == currentDevice) {
                logger.warn("设备【{}】掉线了，等待设备准备好再打开图片流........", adbDevice.getSerial());
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    break;
                }
                continue;
            }
            logger.info("开启设备【{}】的屏幕监听。。。。。。。。。。", adbDevice.getSerial());
            this.asyncAgentSession = new AndroidAgentSession(adbDevice, true);
            try {
                this.asyncAgentSession.start();
                this.asyncAgentSession.send(WatchScreenStreamCommand.getInstance());
                logger.debug("开启屏幕=====>width：{} height:{} quality:{} frameRate:{},rotation:{}", catchParam.getWidth(), catchParam.getHeight(), catchParam.getQuality(), catchParam.getFrameRate(), catchParam.getRotation());
                ScreenStreamCommand screenStreamCommand = new ScreenStreamCommand(true, catchParam.getRotation(), catchParam.getWidth(), catchParam.getHeight(), catchParam.getFrameRate(), catchParam.getQuality());
                this.asyncAgentSession.send(screenStreamCommand);
            } catch (IOException e) {
                logger.error("创建设备【{}】agentSession出错。。。。。。", adbDevice.getSerial(), e);
                interrupt();
                if (!CollectionUtils.isEmpty(webSessions)) {
                    //通知前端断开
                    Map<String, Object> result = new HashMap<>();
                    result.put(ResponseCmd.DeviceStatus.STATUS, ResponseCmd.DeviceStatus.DISCONNECT);
                    for (Session webSession : webSessions) {
                        if (webSession.isOpen()) {
                            SessionUtils.sendMessageInitiative(webSession, ResponseCmd.DEVICE_STATUS, adbDevice.getSerial(), result, "设备连接失败");
                        }
                    }
                }
                this.asyncAgentSession.closeSilence();
                break;
            }
//            sendConnectInfo2Web();
            DataInput dataInput = this.asyncAgentSession.getDataInput();
            int receive = 1;
            int send = 1;
            while (!isInterrupted()) {
                try {
                    int commandId = dataInput.readInt();
//                    logger.debug("屏幕读取线程commandId:{}",commandId);
                    if (commandId == WatchScreenStreamCommand.getInstance().getCommandId()) {//屏幕流
                        byte[] screenPicContent = new byte[0];
                        try {
                            screenPicContent = WatchScreenStreamCommand.getInstance().buildReceive(dataInput);
                            //将获取的最新帧进行缓存
                            if (null != screenPicContent && screenPicContent.length > 0) {
                                this.lastData = screenPicContent;
                                logger.info("设备【{}】收到图片：{}张,大小：{}",adbDevice.getSerial(),receive++,screenPicContent.length);
                            } else {
                                logger.warn("设备【{}】command读取最新帧为空!",adbDevice.getSerial());
                                logger.info("设备【{}】收到图片：{}张,大小为零",adbDevice.getSerial(),receive++);
                                continue;
                            }
                        } catch (IOException e) {
                            logger.error("读取数据出错了", e);
                            break;
                        }
                        //录屏
                        if (null != screenRecorder) {
                            screenRecorder.addImgToVideo(this.lastData);
                        }
                        //有后端会话则给后端推送屏幕图片
                        if (!CollectionUtils.isEmpty(webSessions)) {
                            Iterator<Session> iterator = webSessions.iterator();
                            while (iterator.hasNext()) {
                                Session webSession = iterator.next();
                                if (webSession.isOpen()) {
                                    if (sendDeviceStatus) {
                                        Map<String, Object> result = new HashMap<>();
                                        result.put(ResponseCmd.DeviceStatus.STATUS, ResponseCmd.DeviceStatus.CONNECTED);
                                        SessionUtils.sendMessageInitiative(webSession, ResponseCmd.DEVICE_STATUS, adbDevice.getSerial(), result, "设备连接失败");
                                        sendDeviceStatus = false;
                                    }
                                    SessionUtils.sendBinary(webSession, this.lastData);
                                } else {
                                    logger.warn("推送到web端的session已经断开，sessionId:{}",webSession.getId());
                                    iterator.remove();
                                }
                            }
                        }
                    }
                } catch (IOException e) {
                    logger.warn("读取设备【{}】agentSession输出出错", adbDevice.getSerial(), e);
                    break;
                }
            }
            this.asyncAgentSession.closeSilence();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                break;
            }
            logger.warn("重新建立设备【{}】图片传输的连接...........................", adbDevice.getSerial());
        }
        logger.warn("设备【{}】响应到上位机的屏幕线程退出..........................", adbDevice.getSerial());
    }

    @Override
    public void changeScreenSize() {
        if (null != this.asyncAgentSession) {
            logger.info("改变设备【{}】屏幕的宽高..........................", adbDevice.getSerial());
            ScreenStreamCommand screenStreamCommand = new ScreenStreamCommand(true, catchParam.getRotation(), catchParam.getWidth(), catchParam.getHeight(), catchParam.getFrameRate(), catchParam.getQuality());
            this.asyncAgentSession.send(screenStreamCommand);
        }
    }

    @Override
    public void stopFetchPic() {
        logger.warn("设备【{}】即将退出屏幕获取线程...", adbDevice.getSerial());
        ScreenStreamCommand screenStreamCommand = new ScreenStreamCommand(false, catchParam.getRotation(), catchParam.getWidth(), catchParam.getHeight(), catchParam.getFrameRate(), catchParam.getQuality());
        asyncAgentSession.send(screenStreamCommand);
        asyncAgentSession.closeSilence();
        this.lastData = null;
        AndroidDeviceManager.getInstance().removeScreenThread(adbDevice.getSerial());
        interrupt();
    }
}
