package net.northking.cctp.upperComputer.automation.handler;

import net.northking.cctp.upperComputer.automation.constants.Command;
import net.northking.cctp.upperComputer.automation.constants.UpperParamKey;
import net.northking.cctp.upperComputer.automation.entity.CmdAutomationRequest;
import net.northking.cctp.upperComputer.automation.entity.CmdAutomationResponse;
import net.northking.cctp.upperComputer.automation.entity.ScreenInfo;
import net.northking.cctp.upperComputer.constants.HarmonyKeyBoardCodeEnum;
import net.northking.cctp.upperComputer.deviceManager.HarmonyDeviceManager;
import net.northking.cctp.upperComputer.deviceManager.thread.HarmonyProvider;
import net.northking.cctp.upperComputer.driver.harmony.HarmonyDevice;
import net.northking.cctp.upperComputer.driver.harmony.hyppium.data.DisplaySize;
import net.northking.cctp.upperComputer.driver.harmony.ui.UiComponent;
import net.northking.cctp.upperComputer.driver.ios.command.data.DragXYData;
import net.northking.cctp.upperComputer.driver.ios.command.data.TapXYData;
import net.northking.cctp.upperComputer.exception.ExecuteException;
import net.northking.cctp.upperComputer.utils.deviceHepler.harmony.HarmonyHandlerHelper;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.websocket.Session;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author : yineng.huang
 * @date : 2024/10/29 17:26
 */
public class HarmonyAutomationHandler extends AbstractAutomationHandler {

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

    private HarmonyDevice harmonyDevice;

    private XPath xpath;

    private DocumentBuilder builder;

    public HarmonyAutomationHandler(Session session, HarmonyDevice device) {
        super();
        this.engineSession = session;
        this.harmonyDevice = device;
        this.serial = device.getHdcDevice().getConnectKey();
        this.deviceHandleHelper = new HarmonyHandlerHelper();
        initScreenData();
        XPathFactory xpathFactory = XPathFactory.newInstance();
        xpath = xpathFactory.newXPath();
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        try {
            builder = factory.newDocumentBuilder();
        } catch (ParserConfigurationException e) {
            logger.error("Document创建失败", e);
            throw new ExecuteException("无法创建自动化环境，Xpath构建工具无法初始化");
        }
    }


    @Override
    public void destroy() {

    }

    @Override
    public void openMobileNotificationBar(CmdAutomationRequest request) {

    }

    @Override
    public void closeMobileNotificationBar(CmdAutomationRequest request) {

    }

    @Override
    public void initApplication(CmdAutomationRequest request) {
        CmdAutomationResponse response = null;
        Map<String, String> data = new HashMap<>();
        try {
            Map<String, Object> initData = request.getData();
            boolean reInstall = false;
            if (null != initData.get("forceReInstall")) {
                reInstall = (boolean) initData.get("forceReInstall");
            }
            boolean coverInstall = false;
            if (null != initData.get("coverInstall")) {
                coverInstall = (boolean) initData.get("coverInstall");
            }
            logger.debug("覆盖安装：{}",coverInstall);
            String appId = (String) initData.get("appId");
            Map<String, Object> appDetail = null;
            try {
                appDetail = getAppDetail(appId);
            } catch (Exception e) {
                logger.error("查询app信息出错，原因：", e);
                response = CmdAutomationResponse.builderFailure(request, "查询app信息出错");
                return;
            }
            if (null == appDetail) {
                response = CmdAutomationResponse.builderFailure(request, "app应用已被删除，无法初始化");
                return;
            }
            String appUrl = (String) appDetail.get("appUrl");
            String appPackage = (String) appDetail.get("packageName");
            String appVersion = (String) appDetail.get("buildVersion");
            String appName = appUrl.substring(appUrl.lastIndexOf("_") + 1);
            boolean appInstalled = deviceHandleHelper.isAppInstalled(serial, appPackage);
            logger.debug("手机[{}]上app[{}]安装的结果：{}",serial,appPackage,appInstalled);
            boolean needInstall = !appInstalled;
            if (reInstall) {  //选择了卸载安装
                if (appInstalled) {
                    logger.info("开始从设备【{}】卸载 app[{}] ...", serial, appPackage);
                    deviceHandleHelper.removeApp(serial, appPackage);
                    logger.info("从设备【{}】上卸载App[{}] 完成", serial, appPackage);
                } else {
                    logger.info("设备【{}】上App[{}]未安装，无需卸载", serial, appPackage);
                }
                needInstall = true;
            }else if (coverInstall) { //覆盖安装
                if (appInstalled) {
                    String oldPackageCode = deviceHandleHelper.getOldPackageCode(serial, appPackage);
                    logger.debug("选择了覆盖安装，设备【{}】上app【{}】的版本是：{}", serial, appPackage, oldPackageCode);
                } else {
                    logger.info("设备【{}】上App[{}]未安装", serial, appPackage);
                }
                needInstall = true;
            }
            if(needInstall) {
                boolean installSuccess = installApp(appId, appName);
                if (!installSuccess) {
                    response = CmdAutomationResponse.builderFailure(request, "app安装失败").withData(data);
                    return;
                }
            }
            if (!deviceHandleHelper.isAppInstalled(serial, appPackage)) {
                response = CmdAutomationResponse.builderFailure(request, "app安装失败").withData(data);
                return;
            }
            logger.info("activate app[{}]", appPackage);
            boolean success = deviceHandleHelper.activateApp(this.serial, appPackage);
            if (!success) {
                response = CmdAutomationResponse.builderFailure(request, "应用启动失败");
            } else {
                response = CmdAutomationResponse.builderSuccess(request, "app初始化成功");
            }
        } catch (Exception e) {
            logger.error("设备【{}】应用初始化失败", this.serial, e);
            CmdAutomationResponse.builderFailure(request, "应用初始化失败");
        } finally {
            sendResultToEngine(response);
        }
        logger.info("自动化执行环境【device:{}】准备就绪", this.serial);
    }

    @Override
    public void clickPoint(CmdAutomationRequest request) {
        CmdAutomationResponse response = CmdAutomationResponse.builderFailure(request, "点击失败").withData(false);
        Map<String, Object> data = request.getData();
        try {
            Integer x = (Integer) data.get(UpperParamKey.X);
            Integer y = (Integer) data.get(UpperParamKey.Y);
            TapXYData tapXYData = new TapXYData();
            tapXYData.setX(x);
            tapXYData.setY(y);
            click(tapXYData);
            response = CmdAutomationResponse.builderSuccess(request, "点击成功").withData(true);
        } catch (Exception e) {
            logger.error("输入失败，原因：", e);
            response = CmdAutomationResponse.builderFailure(request, e.getMessage());
        } finally {
            sendResultToEngine(response);
        }
    }

    @Override
    public void searchNodeByNodeTree(CmdAutomationRequest request) {
        CmdAutomationResponse response = CmdAutomationResponse.builderFailure(request, "查找控件完成");
        Map<String, Object> data = request.getData();
        try {
            TapXYData xyData = findNodeByXml(request);
            if (null == xyData) {
                response = CmdAutomationResponse.builderFailure(request, "元素不存在");
            }else {
                response = CmdAutomationResponse.builderSuccess(request, "查找控件完成").withData(xyData);
            }
        } catch (Exception e) {
            logger.error("根据xpath判断元素是否存在失败，原因：", e);
            response = CmdAutomationResponse.builderFailure(request, e.getMessage());
        } finally {
            logger.info("根据nodetree查找元素失败的response：{}", response);
            sendResultToEngine(response);
        }
    }

    @Override
    public void searchNodeByPoint(CmdAutomationRequest request) {
        CmdAutomationResponse response = CmdAutomationResponse.builderFailure(request, "未查找到控件");
        try {
            Map<String, Object> data = request.getData();
            TapXYData tapXYData = null;
            tapXYData = queryPoint(request);
            if (null == tapXYData) {
                response = CmdAutomationResponse.builderFailure(request, "查找控件失败").withData(false);
            } else {
                tapXYData.setX(tapXYData.getX());
                tapXYData.setY(tapXYData.getY());
                //转换比例
                int width = screenInfo.getWidth();
                int height = screenInfo.getHeight();
                int realityWidth = width;
                int realityHeight = height;
                if (width > height) {  //宽高反了的情况，调换
                    realityWidth = height;
                    realityHeight = width;
                }
                Double realityX = (double) tapXYData.getX() / screenInfo.getWidth() * realityWidth;
                Double realityY = (double) tapXYData.getY() / screenInfo.getHeight() * realityHeight;
                tapXYData.setX(realityX.intValue());
                tapXYData.setY(realityY.intValue());
                response = CmdAutomationResponse.builderSuccess(request, "查找控件完成").withData(tapXYData);
            }
        } catch (Exception e) {
            logger.error("根据坐标是否存在失败，原因：", e);
            response = CmdAutomationResponse.builderFailure(request, e.getMessage());
        } finally {
            sendResultToEngine(response);
        }
    }

    @Override
    public void searchNodeByOcr(CmdAutomationRequest request) {
        CmdAutomationResponse response = CmdAutomationResponse.builderFailure(request, "未查找到控件");
        try {
            TapXYData tapXYData = queryClickTextOcrArea(request);
            if (null == tapXYData) {
                response = CmdAutomationResponse.builderFailure(request, "未查找到控件");
            } else {
                //转换比例
                int width = screenInfo.getWidth();
                int height = screenInfo.getHeight();
                int realityWidth = width;
                int realityHeight = height;
                if (width > height) {  //宽高反了的情况，调换
                    realityWidth = height;
                    realityHeight = width;
                }
                Double realityX = (double) tapXYData.getX() / screenInfo.getWidth() * realityWidth;
                Double realityY = (double) tapXYData.getY() / screenInfo.getHeight() * realityHeight;
                tapXYData.setX(realityX.intValue());
                tapXYData.setY(realityY.intValue());
                response = CmdAutomationResponse.builderSuccess(request, "查找控件完成").withData(tapXYData);
            }
        } catch (Exception e) {
            response = CmdAutomationResponse.builderFailure(request, e.getMessage());
        } finally {
            sendResultToEngine(response);
        }
    }

    @Override
    public void searchNodeByImage(CmdAutomationRequest request) {
        CmdAutomationResponse response = CmdAutomationResponse.builderFailure(request, "未查找到控件");
        try {
            Map<String, Object> data = request.getData();
            Integer waitTimeout = (Integer) data.get(UpperParamKey.WAIT_TIMEOUT);
            Integer times = (Integer) data.get(UpperParamKey.TIMES);
            TapXYData tapXYData = null;
            if (null == times) {
                long startTime = System.currentTimeMillis(); //当前时间
                long elapsedTime = 0; // 初始化经过的时间
                while (elapsedTime < waitTimeout * 1000) {
                    tapXYData = queryImageArea(request);
                    if (tapXYData != null) {
                        break;
                    } else {
                        try {
                            if (System.currentTimeMillis() - startTime + 2000 < waitTimeout * 1000) {
                                Thread.sleep(2000);
                            }
                        } catch (InterruptedException e) {
                            logger.warn("查找控件失败", e);
                        }
                    }
                    long currentTime = System.currentTimeMillis();
                    elapsedTime = currentTime - startTime;
                }
            } else {
                tapXYData = queryImageArea(request);
            }
            if (null == tapXYData) {
                response = CmdAutomationResponse.builderFailure(request, "未查找到控件");
            } else {
                //转换比例
                int width = screenInfo.getWidth();
                int height = screenInfo.getHeight();
                int realityWidth = width;
                int realityHeight = height;
                if (width > height) {  //宽高反了的情况，调换
                    realityWidth = height;
                    realityHeight = width;
                }
                Double realityX = (double) tapXYData.getX() / screenInfo.getWidth() * realityWidth;
                Double realityY = (double) tapXYData.getY() / screenInfo.getHeight() * realityHeight;
                tapXYData.setX(realityX.intValue());
                tapXYData.setY(realityY.intValue());
                response = CmdAutomationResponse.builderSuccess(request, "查找控件完成").withData(tapXYData);
            }
        } catch (Exception e) {
            logger.error("根据图像是否存在失败，原因：", e);
            response = CmdAutomationResponse.builderFailure(request, e.getMessage());
        } finally {
            sendResultToEngine(response);
        }
    }

    @Override
    public void getElementValueByNode(CmdAutomationRequest request) {
        CmdAutomationResponse response = CmdAutomationResponse.builderFailure(request, "未查到控件");
        try {
            NodeList nodeList = findElementByXml(request);
            if (null != nodeList && nodeList.getLength() > 0) {
                Element item = (Element) nodeList.item(0);
                String value = item.getAttribute("text");
                if (StringUtils.isNotBlank(value)) {
                    response = CmdAutomationResponse.builderSuccess(request, "已获取控件的值").withData(value);
                } else {
                    response = CmdAutomationResponse.builderFailure(request, "无法获取控件的值");
                }
            } else {
                response = CmdAutomationResponse.builderFailure(request, "找不到控件");
            }
        } catch (Exception e) {
            logger.error("根据xpath获取控件的值失败，原因：", e);
            response = CmdAutomationResponse.builderFailure(request, e.getMessage());
        } finally {
            sendResultToEngine(response);
        }
    }

    @Override
    public void getElementValueByOcr(CmdAutomationRequest request) {
        CmdAutomationResponse response = CmdAutomationResponse.builderFailure(request, "根据ocr获取控件值失败");
        try {
            String value = null;
            Map<String, Object> requestData = request.getData();
            String targetBase64 = "";
            if (requestData.get(UpperParamKey.X) != null) {
                targetBase64 = getOcrAreaToBase64(request);
            } else {
                targetBase64 = getClickTextOcrAreaToBase64(request);
            }
            if (StringUtils.isBlank(targetBase64)) {
                response = CmdAutomationResponse.builderFailure(request, "未获取到ocr区域");
                return;
            }
            value = ocrHelper.getTextValue(targetBase64);
            logger.info("识别的图片文字为：{}", value);
            if (StringUtils.isNotBlank(value)) {
                response = CmdAutomationResponse.builderSuccess(request, "根据ocr获取控件值成功").withData(value);
            } else {
                response = CmdAutomationResponse.builderFailure(request, "根据ocr获取控件值失败");
            }
        } catch (Exception e) {
            logger.error("根据ocr获取控件的值失败，原因：", e);
            response = CmdAutomationResponse.builderFailure(request, e.getMessage());
        } finally {
            sendResultToEngine(response);
        }
    }

    @Override
    public void getVerificationCodeByNode(CmdAutomationRequest request) {

    }

    @Override
    public void getVerificationCodeByOcr(CmdAutomationRequest request) {

    }

    @Override
    public void longPress(CmdAutomationRequest request) {
        CmdAutomationResponse response = CmdAutomationResponse.builderFailure(request, "长按失败").withData(false);
        Map<String, Object> data = request.getData();
        try {
            HarmonyProvider harmonyProvider = getHarmonyProvider();
            if (null == harmonyProvider) {
                response = CmdAutomationResponse.builderFailure(request, "设备与上位机连接断开");
                return;
            }
            int x = (int) data.get(UpperParamKey.X);
            int y = (int) data.get(UpperParamKey.Y);
            logger.debug("步骤【{}】长按的位置----->x:{},y:{}", request.getStepToken(), x, y);
            boolean success = harmonyProvider.touchDown(x, y);
            Thread.sleep(2000);
            success = harmonyProvider.touchUp(x, y);
            if (success) {
                response = CmdAutomationResponse.builderSuccess(request, "长按成功").withData(success);
            } else {
                response = CmdAutomationResponse.builderFailure(request, "长按失败");
            }
        } catch (Exception e) {
            logger.error("输入失败，原因：", e);
            response = CmdAutomationResponse.builderFailure(request, e.getMessage());
        } finally {
            sendResultToEngine(response);
        }
    }

    @Override
    public void swipe(CmdAutomationRequest request) {
        CmdAutomationResponse response = CmdAutomationResponse.builderFailure(request, "滑动失败");
        try {
            Map<String, Object> data = request.getData();
            String direction = (String) data.get(UpperParamKey.SWIPE_DIRECTION);
            Integer size = (Integer) data.get(UpperParamKey.SWIPE_SIZE);
            try {
                boolean success = swipeScreen(direction, size);
                if (success) {
                    response = CmdAutomationResponse.builderSuccess(request, "滑动成功").withData(success);
                } else {
                    response = CmdAutomationResponse.builderFailure(request, "滑动失败");
                }
            } catch (Exception e) {
                logger.error("滑动失败，原因：", e);
                response = CmdAutomationResponse.builderFailure(request, e.getMessage());
            }
        } finally {
            sendResultToEngine(response);
        }
    }

    @Override
    public void inputText(CmdAutomationRequest request) {
        CmdAutomationResponse response = CmdAutomationResponse.builderFailure(request, "输入失败").withData(false);
        Map<String, Object> data = request.getData();
        try {
            boolean clear = (boolean) data.get(UpperParamKey.CLEAR);
            Integer x = (Integer) data.get(UpperParamKey.X);
            Integer y = (Integer) data.get(UpperParamKey.Y);
            if (clear) {
                String xpath = (String) data.get(UpperParamKey.NODE_TREE);
                logger.debug("步骤【{}】输入前清空数据，xpath:{}", request.getStepToken(), xpath);
                TapXYData tapXYData = new TapXYData();
                tapXYData.setX(x);
                tapXYData.setY(y);
                click(tapXYData);
                HarmonyDevice currentDevice = HarmonyDeviceManager.getInstance().getCurrentDevice(this.serial);
                ArrayList<Integer> keyInt = new ArrayList<>();
                keyInt.add(HarmonyKeyBoardCodeEnum.KEYCODE_CTRL_LEFT.getCode());
                keyInt.add(HarmonyKeyBoardCodeEnum.KEYCODE_A.getCode());
                boolean selectAll = currentDevice.keyEvent(keyInt);//ctrl+a 退格
                if (selectAll) {
                    logger.debug("步骤【{}】输入前清空数据已全选", request.getStepToken());
                } else {
                    logger.debug("步骤【{}】输入前清空数据已全选失败", request.getStepToken());
                }
                List<Integer> delete = new ArrayList<>();
                delete.add(HarmonyKeyBoardCodeEnum.KEYCODE_DEL.getCode());
                boolean deleteAll = currentDevice.keyEvent(delete);//ctrl+a 退格
                if (deleteAll) {
                    logger.debug("步骤【{}】输入前清空数据已清空", request.getStepToken());
                } else {
                    logger.debug("步骤【{}】输入前清空数据未清空",request.getStepToken());
                }
            }

            String inputText = (String) data.get(UpperParamKey.INPUT_TEXT);
            if (StringUtils.isBlank(inputText)) {
                response = CmdAutomationResponse.builderFailure(request, "输入的文本不能为空");
                return;
            }
            logger.debug("步骤【{}】即将输入文本：{}", request.getStepToken(), inputText);
            HarmonyDevice currentDevice = HarmonyDeviceManager.getInstance().getCurrentDevice(this.serial);
            if (null != currentDevice) {
                boolean success= currentDevice.inputText(x, y, inputText);
                if (success) {
                    response = CmdAutomationResponse.builderSuccess(request, "输入成功").withData(success);
                } else {
                    response = CmdAutomationResponse.builderFailure(request, "输入失败").withData(success);
                }
            } else {
                response = CmdAutomationResponse.builderFailure(request, "设备已经掉线，无法输入");
            }

        } catch (Exception e) {
            logger.error("输入失败，原因：", e);
            response = CmdAutomationResponse.builderFailure(request, e.getMessage());
        } finally {
            sendResultToEngine(response);
        }
    }

    @Override
    public void handleNodeByNodeTree(CmdAutomationRequest request) {
        CmdAutomationResponse response = CmdAutomationResponse.builderFailure(request, "根据node节点点击控件失败").withData(false);
        try {
            Map<String, Object> data = request.getData();
            Integer commandId = (Integer) data.get(UpperParamKey.COMMAND_ID);
            TapXYData xyData = findNodeByXml(request);
            if (null == xyData) {
                response = CmdAutomationResponse.builderFailure(request, "控件不存在");
                return;
            }
            click(xyData);
            response = CmdAutomationResponse.builderSuccess(request, "点击成功").withData(true);
        } catch (Exception e) {
            logger.error("根据node节点点击控件失败，原因：", e);
            response = CmdAutomationResponse.builderFailure(request, e.getMessage());
        } finally {
            sendResultToEngine(response);
        }
    }

    @Override
    public void handleNodeByPoint(CmdAutomationRequest request) {
        CmdAutomationResponse response = CmdAutomationResponse.builderFailure(request, "根据坐标点击控件失败").withData(false);
        try {
            Map<String, Object> data = request.getData();
            TapXYData tapXYData = queryPoint(request);
            if (null == tapXYData) {
                response = CmdAutomationResponse.builderFailure(request, "未查找到控件").withData(false);
                return;
            }
            int commandId = (int) data.get(UpperParamKey.COMMAND_ID);
            if (Command.CLICK.getCode() == commandId) {  //点击
                click(tapXYData);
                response = CmdAutomationResponse.builderSuccess(request, "点击控件成功").withData(true);
            }
        } catch (Exception e) {
            logger.error("根据坐标点击控件失败，原因：", e);
            response = CmdAutomationResponse.builderFailure(request, e.getMessage());
        } finally {
            sendResultToEngine(response);
        }
    }

    @Override
    public void handleNodeByOcr(CmdAutomationRequest request) {
        CmdAutomationResponse response = CmdAutomationResponse.builderFailure(request, "根据ocr点击控件失败").withData(false);
        try {
            Map<String, Object> data = request.getData();
            String ocrText = (String) data.get(UpperParamKey.OCR_TEXT);
            if (StringUtils.isBlank(ocrText)) {
                response = CmdAutomationResponse.builderFailure(request, "ocr查找的文本不能为空！");
                return;
            }
            TapXYData point = queryClickTextOcrArea(request);
            if (null == point) {
                response = CmdAutomationResponse.builderFailure(request, "未查找到控件").withData(false);
                return;
            }
            int commandId = (int) data.get(UpperParamKey.COMMAND_ID);
            if (Command.CLICK.getCode() == commandId) {  //点击
                click(point);
                response = CmdAutomationResponse.builderSuccess(request, "点击控件成功").withData(true);
            }
        } catch (Exception e) {
            logger.error("根据ocr点击控件失败，原因：", e);
            response = CmdAutomationResponse.builderFailure(request, e.getMessage());
        } finally {
            sendResultToEngine(response);
        }
    }

    @Override
    public void handleNodeByImage(CmdAutomationRequest request) {
        CmdAutomationResponse response = CmdAutomationResponse.builderFailure(request, "根据图像点击控件失败").withData(false);
        try {
            Map<String, Object> data = request.getData();
//            Integer waitTimeout = (Integer) data.get(UpperParamKey.WAIT_TIMEOUT);
            Integer waitTimeout = 120;
            TapXYData tapXYData = null;
            long startTime = System.currentTimeMillis(); //当前时间
            long elapsedTime = 0; // 初始化经过的时间
            while (elapsedTime < waitTimeout * 1000) {
                tapXYData = queryImageArea(request);
                long currentTime = System.currentTimeMillis();
                elapsedTime = currentTime - startTime;
                if (tapXYData != null) {
                    break;
                } else {
                    try {
                        if (System.currentTimeMillis() - startTime + 2000 < waitTimeout * 1000) {
                            Thread.sleep(2000);
                        }
                    } catch (InterruptedException e) {
                        logger.warn("根据图像点击控件失败", e);
                    }
                }
            }
            if (null == tapXYData) {
                response = CmdAutomationResponse.builderFailure(request, "未找到元素").withData(false);
                return;
            }
            int commandId = (int) data.get(UpperParamKey.COMMAND_ID);
            if (Command.CLICK.getCode() == commandId) {  //点击
                click(tapXYData);
                response = CmdAutomationResponse.builderSuccess(request, "点击控件成功").withData(true);
            }
        } catch (Exception e) {
            logger.error("根据图像点击控件失败，原因：", e);
            response = CmdAutomationResponse.builderFailure(request, e.getMessage());
        } finally {
            sendResultToEngine(response);
        }
    }

    @Override
    public void clickTextByOcr(CmdAutomationRequest request) {

    }

    @Override
    public void clickTextByOcrNew(CmdAutomationRequest request) {

    }

    @Override
    public void ifText(CmdAutomationRequest request) {
        CmdAutomationResponse response = CmdAutomationResponse.builderFailure(request, "根据ocr是否存在文本失败").withData(false);
        try {
            Map<String, Object> data = request.getData();
            String ocrText = (String) data.get(UpperParamKey.OCR_TEXT);
            if (StringUtils.isBlank(ocrText)) {
                response = CmdAutomationResponse.builderFailure(request, "ocr查找的文本不能为空！");
                return;
            }
            TapXYData tapXYData = queryClickTextOcrArea(request);
            if (tapXYData == null) {
                // 执行成功，但找不到文本
                response = CmdAutomationResponse.builderFailure(request, "未查找到文本");
            } else {
                // 转换比例
                int width = screenInfo.getWidth();
                int height = screenInfo.getHeight();
                int realityWidth = width;
                int realityHeight = height;
                if (width > height) {  //宽高反了的情况，调换
                    realityWidth = height;
                    realityHeight = width;
                }
                Double realityX = (double) tapXYData.getX() / screenInfo.getWidth() * realityWidth;
                Double realityY = (double) tapXYData.getY() / screenInfo.getHeight() * realityHeight;
                tapXYData.setX(realityX.intValue());
                tapXYData.setY(realityY.intValue());
                // 执行成功，找到文本
                response = CmdAutomationResponse.builderSuccess(request, "存在文本");
            }
            response.withData(tapXYData);
        } catch (Exception e) {
            // 执行失败
            logger.error("根据ocr是否存在失败，原因：", e);
            response = CmdAutomationResponse.builderFailure(request, e.getMessage());
        } finally {
            sendResultToEngine(response);
        }
    }


    @Override
    public void pressHomeKey(CmdAutomationRequest request) {
        CmdAutomationResponse response = CmdAutomationResponse.builderFailure(request, "点击home键失败").withData(false);
        try {
            HarmonyProvider harmonyProvider = getHarmonyProvider();
            boolean success = harmonyProvider.pressHome();
            if (success) {
                response = CmdAutomationResponse.builderSuccess(request, "点击home键成功").withData(true);
            } else {
                response = CmdAutomationResponse.builderFailure(request, "点击home键失败");
            }
        } catch (Exception e) {
            logger.error("点击home键失败，原因：", e);
            response = CmdAutomationResponse.builderFailure(request, e.getMessage());
        } finally {
            sendResultToEngine(response);
        }
    }




    @Override
    public void pressAndSwipe(CmdAutomationRequest request) {

    }

    @Override
    public void getTextDirectionText(CmdAutomationRequest request) {

    }

    @Override
    public void inputPasswordByOcr(CmdAutomationRequest request) {

    }

    @Override
    public void getElementMoneyText(CmdAutomationRequest request) {

    }

    @Override
    public void getElementValueByPathOcr(CmdAutomationRequest request) {

    }

    @Override
    public void swipeForSwipeToFindTargetElement(CmdAutomationRequest request) {

    }

    @Override
    public void elementSwipe(CmdAutomationRequest request) {
        CmdAutomationResponse response = CmdAutomationResponse.builderFailure(request, "控件滑动失败");
        try {
            Map<String, Object> data = request.getData();
            String direction = (String) data.get(UpperParamKey.SWIPE_DIRECTION);
            Integer size = (Integer) data.get(UpperParamKey.SWIPE_SIZE);
            Integer x1 = (Integer) data.get(UpperParamKey.X);
            Integer y1 = (Integer) data.get(UpperParamKey.Y);
            int x2, y2;
            if ("up".equalsIgnoreCase(direction)) {
                x2 = x1;
                y2 = y1 - size;
            } else if ("down".equalsIgnoreCase(direction)) {
                x2 = x1;
                y2 = y1 + size;
            } else if ("left".equalsIgnoreCase(direction)) {
                x2 = x1 - size;
                y2 = y1;
            } else if ("right".equalsIgnoreCase(direction)) {
                x2 = x1 + size;
                y2 = y1;
            } else {
                response = CmdAutomationResponse.builderFailure(request, "只支持上下左右滑动");
                return;
            }
            HarmonyProvider harmonyProvider = getHarmonyProvider();
            if (null == harmonyProvider) {
                response = CmdAutomationResponse.builderFailure(request, "设备已经掉线");
                return;
            }
            boolean result = harmonyProvider.touchDown(x1, y1);
            result = harmonyProvider.touchMove(x2, y2);
            result = harmonyProvider.touchUp(x2, y2);
            if (result) {
                response = CmdAutomationResponse.builderSuccess(request, "控件滑动成功").withData(result);
            } else {
                response = CmdAutomationResponse.builderFailure(request, "控件滑动失败");
            }
        } catch (Exception e) {
            logger.error("控件滑动失败，原因：", e);
            response = CmdAutomationResponse.builderFailure(request, e.getMessage());
        } finally {
            sendResultToEngine(response);
        }
    }

    private TapXYData queryClickTextOcrArea(CmdAutomationRequest request) {
        TapXYData result = null;
        Map<String, Object> data = request.getData();
        String base64Str = "";
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        String ocrText = (String) data.get(UpperParamKey.OCR_TEXT);
        Integer diffussion = data.get(UpperParamKey.DIFFUSSION) != null ? (Integer) data.get(UpperParamKey.DIFFUSSION) : null;
        Integer index = (Integer) data.get(UpperParamKey.INDEX);
        double realityX = 0.0;
        double realityY = 0.0;
        if (data.get(UpperParamKey.X) != null) {
            base64Str = getOcrAreaToBase64(request);
            Integer x = (Integer) data.get(UpperParamKey.X);
            Integer y = (Integer) data.get(UpperParamKey.Y);
            Integer screenWidth = (Integer) data.get(UpperParamKey.SCREEN_WIDTH);
            Integer screenHeight = (Integer) data.get(UpperParamKey.SCREEN_HEIGHT);
            //转换比例
            int width = screenInfo.getWidth();
            int height = screenInfo.getHeight();
            int realityWidth = width;
            int realityHeight = height;
            if (width > height) {  //宽高反了的情况，调换
                realityWidth = height;
                realityHeight = width;
            }
            realityX = x.doubleValue() / screenWidth.doubleValue() * realityWidth;
            realityY = y.doubleValue() / screenHeight.doubleValue() * realityHeight;
        } else {
            base64Str = getClickTextOcrAreaToBase64(request);
        }
        if (StringUtils.isNotBlank(base64Str)) {
            result = ocrHelper.doFindTextByOcr(base64Str, ocrText, diffussion, index, realityX, realityY);
        }
        return result;
    }


    @Override
    public void initScreenData() {
        this.screenInfo = new ScreenInfo();
        HarmonyProvider harmonyProvider = getHarmonyProvider();
        DisplaySize screenSize = harmonyProvider.getScreenSize();
        if (null == screenSize) {
            throw new ExecuteException("获取当前手机的屏幕信息失败");
        }
        screenInfo.setHeight(screenSize.height);
        screenInfo.setWidth(screenSize.width);
        logger.info("当前手机【{}】的宽：{}，高：{}", this.serial, screenInfo.getWidth(), screenInfo.getHeight());
    }

    private HarmonyProvider getHarmonyProvider() {
        HarmonyProvider provider = HarmonyDeviceManager.getInstance().getCurrentDeviceProvider(this.serial);
        if (null == provider) {
            throw new ExecuteException("当前设备已经掉线，请检查设备");
        }
        return provider;
    }

    private void click(TapXYData point) {
        logger.debug("设备【{}】实际点击的位置------->>>>>>x:{},y:{}", this.serial, point.getX(), point.getY());
        HarmonyProvider harmonyProvider = getHarmonyProvider();
        harmonyProvider.touchDown(point.getX(), point.getY());
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        harmonyProvider.touchUp(point.getX(), point.getY());
        logger.debug("设备【{}】点击操作完成.........", this.serial);
    }

    private boolean swipeScreen(String direction, Integer size) {
        DragXYData dragXYData = calculateSwipePoint(direction, size);
        HarmonyProvider harmonyProvider = getHarmonyProvider();
        harmonyProvider.touchDown(dragXYData.x, dragXYData.y);
        harmonyProvider.touchMove(dragXYData.toX, dragXYData.toY);
        harmonyProvider.touchUp(dragXYData.toX, dragXYData.toY);
        logger.debug("设备【{}】滑动完毕.............", this.serial);
        return true;
    }

    private NodeList findNode(String xpathText, Document document) throws XPathExpressionException {
        XPathExpression expression = xpath.compile(xpathText);
        NodeList nodeList = (NodeList) expression.evaluate(document, XPathConstants.NODESET);
        System.out.println("查找XPath：" + xpathText);
        System.out.println("找到以下节点：");
        for (int i = 0; i < nodeList.getLength(); i++) {
            Element node = (Element) nodeList.item(i);
            System.out.println("<" + node.getNodeName() + " x=" + node.getAttribute("x") + " y=" + node.getAttribute("y") + " width=" + node.getAttribute("width") + " text=" + node.getAttribute("text") + ">");
        }
        return nodeList;
    }

    private TapXYData findNodeByXml(CmdAutomationRequest request){
        NodeList nodeList = findElementByXml(request);
        if (null == nodeList ||  nodeList.getLength() <= 0 ) {
            return null;
        } else {
            TapXYData tapXYData = new TapXYData();
            Element item = (Element) nodeList.item(0);
            Integer width = Integer.parseInt(item.getAttribute("width"));
            Integer height = Integer.parseInt(item.getAttribute("height"));
            Integer realityX = Integer.parseInt(item.getAttribute("x"));
            Integer realityY = Integer.parseInt(item.getAttribute("y"));
            tapXYData.setX((realityX + width / 2));
            tapXYData.setY((realityY + height / 2));
            return tapXYData;
        }
    }

    private NodeList findElementByXml(CmdAutomationRequest request){
        Map<String, Object> data = request.getData();
        String nodeTree = (String) data.get(UpperParamKey.NODE_TREE);
        Integer waitTimeOut = (Integer) data.get(UpperParamKey.WAIT_TIMEOUT);
        String swipe = (String) data.get(UpperParamKey.IS_SWIPE);
        Integer swipeCount = (Integer) data.get(UpperParamKey.SWIPE_COUNT);
        logger.debug("拿到的nodeTree:{}", nodeTree);
        long startTime = System.currentTimeMillis();
        long endTime = startTime;
        if ((swipeCount <= 0 || swipeCount > 5) || "0".equals(swipe)) {  //超过5次不给滑或者选择不滑屏
            swipeCount = 0;
        }
        int perSwipeTime = waitTimeOut;
        if (swipeCount > 0) {
            perSwipeTime = waitTimeOut / swipeCount;
            if (perSwipeTime <= 0) {  //防止每次超时时间过小
                perSwipeTime = 1;
            }
        }
        logger.debug("步骤：{}开始查找控件，滑屏：{}，滑动次数：{}，每次查找超时时间：{}，总超时时间：{}", request.getStepToken(), swipe, swipeCount, perSwipeTime, waitTimeOut);
        boolean alreadyFind = false;
        int screenIndex = 1;
        NodeList nodeList = null;
        while (!alreadyFind) {
            int findIndex = 1;
            do {
                logger.debug("步骤：{}，第{}屏，第{}次开始查找元素", request.getStepToken(), screenIndex, findIndex);
                HarmonyProvider harmonyProvider = getHarmonyProvider();
                UiComponent uiComponent = harmonyProvider.captureLayout();
                Document document = builder.newDocument();
                Node xmlElement = uiComponent.createXMLElement(document);
                document.appendChild(xmlElement);
                try {
                    nodeList = findNode(nodeTree, document);
                } catch (XPathExpressionException e) {
                    logger.error("步骤：{}，xpath格式不对：{}",request.getStepToken(),nodeTree);
                    return null;
                }
                endTime = System.currentTimeMillis();
                logger.debug("步骤：{}，第{}次查找元素的总时间（累加）：{}ms，结果：nodeList是否是空：{}", request.getStepToken(), findIndex, endTime - startTime, null == nodeList);
                findIndex++;
                if (null != nodeList && nodeList.getLength() > 0) {
                    alreadyFind = true;
                    break;
                }
            } while ((endTime - startTime) < perSwipeTime * 1000);
            logger.debug("步骤：{}，第{}屏,查找的结果：{},nodeList是否是空：{}", request.getStepToken(), screenIndex, alreadyFind,  null == nodeList);
            if (alreadyFind) {  //找到了，不用找了
                logger.debug("步骤：{}，第{}屏,找到了，不找了", request.getStepToken(), screenIndex);
                break;
            } else {   //没找到，滑不滑动屏幕
                swipeCount--;
                if (swipeCount < 0) {
                    logger.debug("步骤：{}，第{}屏，没找到元素，不滑屏了", request.getStepToken(), screenIndex);
                    break;
                } else {
                    logger.debug("步骤：{}，第{}屏，没找到元素，滑一下再继续找", request.getStepToken(), screenIndex);
                    boolean success = swipeScreen(swipe, 500);//固定的滑动方向，滑动的commandId为24
                    if (success) {
                        logger.debug("步骤：{}，第{}次滑动：{}屏幕成功", request.getStepToken(), screenIndex, swipe);
                    } else {
                        logger.debug("步骤：{}，第{}次滑动：{}屏幕失败", request.getStepToken(), screenIndex, swipe);
                    }
                    screenIndex++;
                }
            }
        }
        return nodeList;
    }
}
