package net.northking.cctp.upperComputer.deviceManager;

import com.alibaba.fastjson.JSON;
import net.northking.cctp.upperComputer.deviceManager.thread.AndroidDeviceInitThread;
import net.northking.cctp.upperComputer.driver.adb.Adb;
import net.northking.cctp.upperComputer.driver.adb.AdbDevice;
import net.northking.cctp.upperComputer.driver.adb.AndroidDeviceListener;
import net.northking.cctp.upperComputer.webSocket.thread.AndroidScreenResponseThread;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class AndroidDeviceManager extends AbstractDeviceManager {

    private static AndroidDeviceManager androidDeviceManager;

    public static AndroidDeviceManager getInstance() {
        if (androidDeviceManager == null) {
            androidDeviceManager = new AndroidDeviceManager();
            try {
                androidDeviceManager.adb = new Adb();
            } catch (IOException e) {
                logger.warn("adb对象创建失败", e);
            }
        }
        return androidDeviceManager;
    }

    private Adb adb;

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

    /**
     * android设备初始化线程
     */
    private ConcurrentHashMap<String, AndroidDeviceInitThread> onlineDeviceInitMap = new ConcurrentHashMap<>();

    /**
     * android设备初始化线程
     */
    private ConcurrentHashMap<String, Boolean> deviceSystemIsReady = new ConcurrentHashMap<>();


    /**
     * android推送屏幕
     */
    public ConcurrentHashMap<String, AndroidScreenResponseThread> screenMap = new ConcurrentHashMap<>();

    public void saveDeviceScreenThread(String deviceId, AndroidScreenResponseThread screenResponseThread){
        this.screenMap.put(deviceId, screenResponseThread);
    }

    public AndroidScreenResponseThread getScreenThread(String deviceId){
        return this.screenMap.get(deviceId);
    }

    public AndroidScreenResponseThread removeScreenThread(String deviceId){
        return this.screenMap.remove(deviceId);
    }


    /**
     * 设置设备系统状态，true是准备好，false未准备好
     * @param serial
     * @param status
     */
    @Override
    public void setDeviceSystemStatus(String serial, Boolean status) {
        deviceSystemIsReady.put(serial, status);
    }

    @Override
    public void shutdown() {
        clearAndShutdownDevices();
    }


    public AdbDevice getCurrentDevice(String deviceId) {
        AndroidDeviceInitThread initThread = onlineDeviceInitMap.get(deviceId);
        if (null != initThread && initThread.isAlive() && !initThread.isInterrupted()) {
            if (initThread.isAgentStatus()) {
                return initThread.getAdbDevice();
            }
        } else {
            logger.warn("当前设备不在线：{}",deviceId);
        }
        return null;
    }

    public AndroidDeviceInitThread getAndroidInitThread(String serial){
        return onlineDeviceInitMap.get(serial);
    }


    public Adb getAdb() {
        return adb;
    }

    @Override
    public void run() {
        while (!isInterrupted()) {
            startAdbServer();
            try {
                adb.watchDevice(new AndroidDeviceListener());
            } catch (Exception e) {
                logger.warn("Android设备监听失败",e);
            }
        }
        logger.warn("android设备监听退出。。。。。。。。。。。。");
    }

    private void startAdbServer() {
        String[] cmd = {"adb", "devices"};
        ProcessBuilder builder = new ProcessBuilder(Arrays.asList(cmd)).redirectErrorStream(true);
        try {
            Process process = builder.start();
            process.waitFor();
        } catch (IOException e) {
            logger.warn("adb服务异常",e);
        } catch (InterruptedException e) {
            interrupt();
            return;
        }
    }

    public void handleAndroidDevice(ArrayList<AdbDevice> currentDevices) {
        List<AdbDevice> onlineDevices = new ArrayList<>();
        List<String> offlineDevices = new ArrayList<>();
        checkAndroidDevice(currentDevices,offlineDevices,onlineDevices);
        if (!CollectionUtils.isEmpty(onlineDevices)) {  //设备上线
            for (AdbDevice adbDevice : onlineDevices) {
                logger.info("新上来设备：{}", JSON.toJSONString(adbDevice));
                if (AdbDevice.State.Device == adbDevice.state) {
                    //注册并启动agent
                    AndroidDeviceInitThread androidDeviceInitThread = new AndroidDeviceInitThread(adb,adbDevice);
                    androidDeviceInitThread.start();
                    onlineDeviceInitMap.put(adbDevice.getSerial(), androidDeviceInitThread);
                    publishDeviceOnlineToWebConnection(adbDevice.getSerial());
                }
            }
        }
        //下线
        if (!CollectionUtils.isEmpty(offlineDevices)) {
            for (String deviceId : offlineDevices) {
                logger.warn("设备【{}】下线", deviceId);
                AndroidDeviceInitThread deviceInitThread = onlineDeviceInitMap.remove(deviceId);
                if (deviceInitThread != null && deviceInitThread.isAlive() && !deviceInitThread.isInterrupted()) {
                    deviceInitThread.exit();
                }
                offlineDeviceFromDeviceManager(deviceId);
                //设备下线，停止获取屏幕线程
                publishDeviceOfflineToWebConnection(deviceId);
            }
        }
    }



    /**
     * 检查哪些设备上线，下线，持有状态不变
     * @param currentDevices  adb检测到变化的设备
     * @param offlineDevices  下线的设备
     * @param onlineDevices   上线的设备
     */
    private void checkAndroidDevice(ArrayList<AdbDevice> currentDevices, List<String> offlineDevices, List<AdbDevice> onlineDevices) {
        Map<String, AdbDevice> currentDeviceMap = new HashMap<>();
        //检查上线
        for (AdbDevice currentDevice : currentDevices) {
            currentDeviceMap.put(currentDevice.getSerial(), currentDevice);
            if (onlineDeviceInitMap.containsKey(currentDevice.getSerial())) {  //原来有
                logger.debug("adb检测到设备：{},该设备已经上线。。。。。。。", currentDevice.getSerial());
            } else {
                onlineDevices.add(currentDevice);
            }
        }
        //检查下线
        ConcurrentHashMap.KeySetView<String, AndroidDeviceInitThread> keySet = onlineDeviceInitMap.keySet();
        for (String deviceId : keySet) {
            if (!currentDeviceMap.containsKey(deviceId)) {
                offlineDevices.add(deviceId);
            }
        }
    }


    public boolean checkMobileIsOnline(String serial) {
        AndroidDeviceInitThread initThread = onlineDeviceInitMap.get(serial);
        if (null != initThread && !initThread.isInterrupted() && initThread.isAlive()) {
            return true;
        }
        return false;
    }

    private void clearAndShutdownDevices(){
        for (Map.Entry<String, AndroidDeviceInitThread> initThreadEntry : onlineDeviceInitMap.entrySet()) {
            AndroidDeviceInitThread initThread = initThreadEntry.getValue();
            initThread.exit();
        }
        onlineDeviceInitMap.clear();
        //停止屏幕获取线程
        for (AndroidScreenResponseThread screenResponseThread : screenMap.values()) {
            logger.debug("上位机重启，中断残余获取屏幕线程");
            if (null != screenResponseThread && screenResponseThread.isAlive() && !screenResponseThread.isInterrupted()) {
                screenResponseThread.stopAndExit();
            }
        }
        screenMap.clear();
        interrupt();
    }

    @Override
    public List<String> getOnlineDevice() {
        List<String> list = new ArrayList<>();
        Collection<AndroidDeviceInitThread> deviceInitThreads = onlineDeviceInitMap.values();
        for (AndroidDeviceInitThread initThread : deviceInitThreads) {
            if (initThread.isAlive() && !initThread.isInterrupted()) {
                if (initThread.isAgentStatus()) {
                    list.add(initThread.getAdbDevice().getSerial());
                }
            }
        }
        return list;
    }

}
