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

import com.alibaba.fastjson.JSON;
import net.northking.cctp.upperComputer.config.BuildWdaConfig;
import net.northking.cctp.upperComputer.deviceManager.IOSDeviceManager;
import net.northking.cctp.upperComputer.deviceManager.UpperComputerManager;
import net.northking.cctp.upperComputer.deviceManager.common.PyMobileDevice;
import net.northking.cctp.upperComputer.deviceManager.entity.DeviceBaseInfo;
import net.northking.cctp.upperComputer.deviceManager.utils.OutputLineCallback;
import net.northking.cctp.upperComputer.deviceManager.utils.XcodeBuild;
import net.northking.cctp.upperComputer.driver.ios.NKAgent;
import net.northking.cctp.upperComputer.driver.ios.command.data.ScreenInfoData;
import net.northking.cctp.upperComputer.driver.usbmuxd.AppleDevice;
import net.northking.cctp.upperComputer.entity.PhoneEntity;
import net.northking.cctp.upperComputer.exception.ExecuteException;
import net.northking.cctp.upperComputer.utils.SpringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.LinkedHashMap;

/**
 * @author : yineng.huang
 * @date : 2023/10/16 14:42
 */
public class MacIosDeviceInitThread extends IosDeviceInitThread {
    private final static Logger logger = LoggerFactory.getLogger(MacIosDeviceInitThread.class);

    /**
     * iOS开始使用CoreDevice框架的版本
     */
    public static final int IOS_CORE_DEVICE_VERSION = 17;

    /**
     * xcodebuild的退出码
     */
    private Integer exitCode = null;

    private String logFileName = null;

    private String xctestPath;

    private OutputLineCallback outputLineCallback;

    public MacIosDeviceInitThread(PhoneEntity phoneEntity, AppleDevice device) {
        super(phoneEntity, device);
        init();
    }

    private void init() {
        int productMainVersion = appleDevice.getProductMainVersion();
        if (productMainVersion < IOS_CORE_DEVICE_VERSION) {
            this.xctestPath = XcodeBuild.getInstance().getSdk16XctestPath();
        } else {
            this.xctestPath = XcodeBuild.getInstance().getDefaultXctestPath();
        }
        if (xctestPath == null) {
            throw new IllegalStateException("未准备好iOS " + productMainVersion + "的xctest");
        }
    }

    @Override
    public void run() {
        BuildWdaConfig wdaConfig = SpringUtils.getBean(BuildWdaConfig.class);
        ProcessBuilder processBuilder = new ProcessBuilder(
                "sudo",
                "-u",
                wdaConfig.getXcodeUsername(),
                "xcodebuild",
                "test-without-building",
                "-xctestrun",
                xctestPath,
                "-destination",
                "id=" + appleDevice.getConnectionDetail().serialNumber
        );
        processBuilder.redirectErrorStream(true);
        while (!isInterrupted()) {
            try {
                process = processBuilder.start();
            } catch (IOException e) {
                logger.error("启动WDA时发生IO异常", e);
                return;
            }
            FileOutputStream logOutput = null;
            File logDir = new File(UpperComputerManager.getInstance().getApplicationPath() + "/wdaLog");
            if (!logDir.exists()) {
                logDir.mkdirs();
            }
            logFileName = logDir.getAbsolutePath() + "/" + "WDA-" + appleDevice.getConnectionDetail().serialNumber + "-" + getLogFileNameDateTime() + ".log";
            try {
                logOutput = new FileOutputStream(logFileName);
            } catch (FileNotFoundException e) {
                logger.error("尝试创建独立日志文件时发生异常", e);
                return;
            }
            InputStreamReader inputStreamReader = null;
            BufferedReader bufferReader = null;
            String line = null;
            try {
                inputStreamReader = new InputStreamReader(process.getInputStream());
                bufferReader = new BufferedReader(inputStreamReader);
                while ((line = bufferReader.readLine()) != null) {
                    if (wdaConfig.isPrintWdaOutput()) {
                        logger.debug("WDA-" + appleDevice.getConnectionDetail().serialNumber + "->" + line);
                    }
                    logOutput.write(line.getBytes());
                    logOutput.write(10);
                    if (!isFBServerReady && line.contains("ServerURLHere")) {
                        logger.debug("发现WDA启动完成信号");
                        isFBServerReady = true;
                        try {
                            createNKAgent("WDA启动");
                        } catch (ExecuteException e) {
                            logger.error("WDA启动后创建NKAgent失败", e);
                            process.destroy();
                            break;
                        }
                        apiPortReady();
                    }
                    if (outputLineCallback != null) {
                        try {
                            outputLineCallback.onLine(line);
                        } catch (Exception e) {
                            logger.error("行回调中发生错误", e);
                        }
                    }
                }
            } catch (IOException e) {
                logger.warn("读取WDA输出时发生IO异常，设备" + appleDevice.getConnectionDetail().serialNumber, e);
            } finally {
                if (null != inputStreamReader) {
                    try {
                        inputStreamReader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (null != bufferReader) {
                    try {
                        bufferReader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            isFBServerReady = false;
            if (nkAgent != null) {
                nkAgent.setOnDisconnectListener(null);
            }
            try {
                exitCode = process.waitFor();
            } catch (InterruptedException ignored) {
                break;
            }
            try {
                logOutput.close();
            } catch (IOException e) {
                logger.warn("关闭WDA独立日志流时发生IO异常，路径:{}", logFileName, e);
            }
            IOSDeviceManager.getInstance().publishDeviceAgentDead(phone.getUdid());
            logger.debug("设备【{}】的wda退出了,重启一次......................", appleDevice.getConnectionDetail().serialNumber);
        }
        logger.debug("设备【{}】的wda退出了,不在重启了......................", appleDevice.getConnectionDetail().serialNumber);
    }


    public void apiPortReady() {
        new Thread(() -> {
            logger.debug("获取设备【{}】的详情参数。。。。。。。", phone.getUdid());
            try {
                deviceInfo = getDeviceInfo();
            } catch (IOException e) {
                logger.error("获取设备信息失败", e);
                return;
            }
            //创建访问session
//            JSONObject sessionObject = null;
//            try {
//                Map<String, Object> paramMap = new HashMap<>();
//                Map<String, Boolean> capabilities = new HashMap<>();
//                capabilities.put("shouldUseTestManagerForVisibilityDetection", false);
//                capabilities.put("shouldUseCompactResponses", false);
//                paramMap.put("capabilities", capabilities);
//                HttpEntity<Map<String, Object>> entity = new HttpEntity<>(paramMap, null);
//                sessionObject = HttpUtils.doPost(new URI("http://localhost:" + phone.getPort8100() + "/session"), entity, JSONObject.class);
//                JSONObject valueMap = sessionObject.getJSONObject("value");
//                if (null != valueMap) {
//                    String sessionId = valueMap.getString("sessionId");
//                    logger.info("设备【{}】得wdaSessionId为：{}", phone.getUdid(), sessionId);
//                    IOSDeviceManager.getInstance().addPhoneSessionId(phone.getUdid(), sessionId);
//                }
//            } catch (URISyntaxException uriSyntaxException) {
//                logger.warn("设备【{}】请求创建session时url不对", phone.getUdid());
//                return;
//            } catch (Exception e) {
//                logger.warn("设备【{}】请求创建session时出错，待会再试", phone.getUdid());
//                return;
//            }
            logger.debug("注册设备信息：{}", JSON.toJSONString(deviceInfo));
            IOSDeviceManager.getInstance().registerDeviceToDeviceManager(deviceInfo);
            phone.setStatus(true);
            IOSDeviceManager.getInstance().publishDeviceAgentAlready(phone.getUdid());
        }).start();
    }

    public NKAgent getNkAgent() {
        return nkAgent;
    }

    public LinkedHashMap<String, Object> getDeviceInfo() throws IOException {
        PyMobileDevice.SpecificAppleDeviceInfo specificAppleDeviceInfo = IOSDeviceManager.getInstance().getSpecificAppleDeviceInfo(appleDevice.getSerial());
        DeviceBaseInfo deviceBaseInfo = PyMobileDevice.getInstance().deviceBaseInfo(specificAppleDeviceInfo);
        logger.debug("获取到手机的详情：{}", JSON.toJSONString(deviceBaseInfo));
        LinkedHashMap<String, Object> deviceInfo = new LinkedHashMap<>();
        //region 平台
        deviceInfo.put("platform", "ios");
        //region 品牌
        deviceInfo.put("manufacturer", deviceBaseInfo.getDeviceClass());
//        //region 型号
        deviceInfo.put("model", deviceBaseInfo.getProductType());
//        //region 产品
        deviceInfo.put("product", deviceBaseInfo.getDeviceName());
        //region 设备号
        deviceInfo.put("serial", phone.getUdid());
//        //region 平台版本
        deviceInfo.put("version", deviceBaseInfo.getProductVersion());
        ScreenInfoData screenInfoData = nkAgent.screenInfo();
        logger.debug("获取到手机的屏幕：{}", JSON.toJSONString(screenInfoData));
        Double width = screenInfoData.getWidth();
        Double height = screenInfoData.getHeight();
        Double scale = screenInfoData.getScale();
        logger.info("手机【{}】的宽:{}高:{},缩放比：{}", phone.getUdid(), width, height, scale);
        phone.setScreenWidth(width.intValue());
        phone.setScreenHeight(height.intValue());
        phone.setScale(scale.intValue());
        //屏幕尺寸
        Double realWidth = width * scale;
        Double realHeight = height * scale;
        deviceInfo.put("width", realWidth.intValue());
        deviceInfo.put("height", realHeight.intValue());
        deviceInfo.put("scale", scale);
        deviceInfo.put("isHarmony", false);
        deviceInfo.put("wdaUrl", "http://" + UpperComputerManager.getInstance().getHost() + ":" + phone.getPort8100());
        int rotation = screenInfoData.getOrientation() - 1;
        if (rotation < 0) {
            logger.debug("无法获取设备【{}】的屏幕方向,默认为0", phone.getUdid());
            rotation = 0;
        }
        deviceInfo.put("rotation", rotation);
        return deviceInfo;
    }

    public void exitWdaAndProxy() {
        if (process != null) {
            process.destroy();
            try {
                exitCode = process.waitFor();
            } catch (InterruptedException e) {
                logger.warn("未能等待获取退出码：线程被中断");
            }
        }
        interrupt();
    }


}
