package net.northking.cctp.element.mobile.keywords;

import cn.hutool.core.util.ReUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import net.northking.cctp.element.core.DeviceDriver;
import net.northking.cctp.element.core.IExecuteContext;
import net.northking.cctp.element.core.IStepTarget;
import net.northking.cctp.element.core.annotation.Argument;
import net.northking.cctp.element.core.annotation.Keyword;
import net.northking.cctp.element.core.annotation.Keywords;
import net.northking.cctp.element.core.annotation.Return;
import net.northking.cctp.element.core.exception.AssertException;
import net.northking.cctp.element.core.exception.EnvironmentException;
import net.northking.cctp.element.core.exception.ExecuteException;
import net.northking.cctp.element.core.exception.ParamMistakeException;
import net.northking.cctp.element.core.type.DataType;
import net.northking.cctp.element.core.type.InputType;
import net.northking.cctp.element.core.type.ParamScope;
import net.northking.cctp.element.mobile.enums.*;
import net.northking.cctp.element.mobile.thread.*;
import net.northking.cctp.element.mobile.utils.HttpUtils;
import org.openqa.selenium.NoSuchSessionException;
import org.openqa.selenium.StaleElementReferenceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

/**
 * <p>android和ios端通用组件</p>
 */
@Keywords
public class CommonTools {

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

    private final ExecutorService executorService = Executors.newCachedThreadPool();

    /**
     * <p>点击文本</p>
     *
     * @param deviceDriver   设备连接驱动
     * @param waitTimeout    默认超时时间
     * @param text           点击的文本
     * @param index          选择第几个
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    @Keyword(alias = "点击文本", category = "0", attributes = "45", commonlyUse = true)
    @Return(name = "result", comment = "是否点击成功", type = DataType.BOOLEAN)
    public Boolean clickText(
            IExecuteContext context,
            @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver,
            @Argument(name = "timeout", scope = ParamScope.ARGS, comment = "默认超时时间", type = DataType.INTEGER, required = false, defaultValue = "30", defaultDisplay = false) Integer waitTimeout,
            @Argument(name = "text", comment = "点击文本", scope = ParamScope.ARGS, type = DataType.STRING) String text,
            @Argument(name = "index", comment = "第几个", scope = ParamScope.ARGS, type = DataType.INTEGER, required = true, defaultValue = "1", defaultDisplay = false) Integer index,
            @Argument(name = "preExecuteWait", scope = ParamScope.ARGS, comment = "执行前等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float preExecuteWait,
            @Argument(name = "sufExecuteWait", scope = ParamScope.ARGS, comment = "执行后等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float sufExecuteWait

    ) {
        ClickTextThread clickTextThread = new ClickTextThread(context,deviceDriver,waitTimeout,preExecuteWait,sufExecuteWait,text,index);
        Future<Boolean> future = executorService.submit(clickTextThread);
        Boolean aBoolean = null;
        deviceDriver.setFuture(future);
        try {
            aBoolean = future.get(waitTimeout, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            //Thread.currentThread().interrupt();
            logger.warn("该线程被中断了。。。。。。");
            throw new ExecuteException("执行中断");
        } catch (ExecutionException e) {
            logger.warn("在执行的时候报错了。。。。");
            Throwable cause = e.getCause();
            if (cause instanceof ExecuteException) {
                ExecuteException ee = (ExecuteException) cause;
                throw ee;
            } else if (cause instanceof ParamMistakeException) {
                ParamMistakeException pe = (ParamMistakeException) cause;
                throw pe;
            } else if (cause instanceof NoSuchSessionException) {
                NoSuchSessionException ne = (NoSuchSessionException) cause;
                throw ne;
            } else if (cause instanceof EnvironmentException) {
                EnvironmentException ee = (EnvironmentException) cause;
                throw ee;
            }else if (cause instanceof StaleElementReferenceException) {
                throw new ExecuteException("当前操作的元素已经失效");
            } else {
                logger.error("出现了其他的问题。。。。", e);
                throw new ExecuteException(cause.getMessage());
            }
        } catch (TimeoutException e) {
            logger.warn("处理超时了。。。。。。");
            throw new ExecuteException("查找文本超时");
        } catch (CancellationException e) {
            logger.warn("该操作被取消了");
            throw new ExecuteException("用户取消，执行失败");
        }
        return aBoolean;
    }

    /**
     * <p>点击文本</p>
     *
     * @param deviceDriver   设备连接驱动
     * @param waitTimeout    默认超时时间
     * @param text           点击的文本
     * @param index          选择第几个
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    @Keyword(alias = "点击文本(新)", category = "0", attributes = "45", commonlyUse = true)
    @Return(name = "result", comment = "是否点击成功", type = DataType.BOOLEAN)
    public Boolean clickTextNew(
            IExecuteContext context,
            @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver,
            @Argument(name = "timeout", scope = ParamScope.ARGS, comment = "默认超时时间", type = DataType.INTEGER, required = false, defaultValue = "30", defaultDisplay = false) Integer waitTimeout,
            @Argument(name = "text", comment = "点击文本", scope = ParamScope.ARGS, type = DataType.STRING) String text,
            @Argument(name = "index", comment = "第几个", scope = ParamScope.ARGS, type = DataType.INTEGER, required = true, defaultValue = "1", defaultDisplay = false) Integer index,
            @Argument(name = "preExecuteWait", scope = ParamScope.ARGS, comment = "执行前等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float preExecuteWait,
            @Argument(name = "sufExecuteWait", scope = ParamScope.ARGS, comment = "执行后等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float sufExecuteWait

    ) {
        ClickTextThreadNew clickTextThread = new ClickTextThreadNew(context,deviceDriver,waitTimeout,preExecuteWait,sufExecuteWait,text,index);
        Future<Boolean> future = executorService.submit(clickTextThread);
        Boolean aBoolean = null;
        deviceDriver.setFuture(future);
        try {
            aBoolean = future.get(waitTimeout, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            //Thread.currentThread().interrupt();
            logger.warn("该线程被中断了。。。。。。");
            throw new ExecuteException("执行中断");
        } catch (ExecutionException e) {
            logger.warn("在执行的时候报错了。。。。");
            Throwable cause = e.getCause();
            if (cause instanceof ExecuteException) {
                ExecuteException ee = (ExecuteException) cause;
                throw ee;
            } else if (cause instanceof ParamMistakeException) {
                ParamMistakeException pe = (ParamMistakeException) cause;
                throw pe;
            } else if (cause instanceof NoSuchSessionException) {
                NoSuchSessionException ne = (NoSuchSessionException) cause;
                throw ne;
            } else if (cause instanceof EnvironmentException) {
                EnvironmentException ee = (EnvironmentException) cause;
                throw ee;
            }else if (cause instanceof StaleElementReferenceException) {
                throw new ExecuteException("当前操作的元素已经失效");
            } else {
                logger.error("出现了其他的问题。。。。", e);
                throw new ExecuteException(cause.getMessage());
            }
        } catch (TimeoutException e) {
            logger.warn("处理超时了。。。。。。");
            throw new ExecuteException("查找文本超时");
        } catch (CancellationException e) {
            logger.warn("该操作被取消了");
            throw new ExecuteException("用户取消，执行失败");
        }
        return aBoolean;
    }


    /**
     * <p>判断当前页面是否存在文本</p>
     *
     * @param deviceDriver   设备连接驱动
     * @param waitTimeout    默认等待时长
     * @param text           判断的文本
     * @param value          接受返回结果
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return 返回判断的结果
     */
    @Keyword(alias = "是否存在文本", category = "0", attributes = "45")
    @Return(name = "result", comment = "文本存在与不存在的结果", type = DataType.BOOLEAN)
    public Boolean ifText(
            IExecuteContext context,
            @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver,
            @Argument(name = "timeout", scope = ParamScope.ARGS, comment = "默认超时时间", type = DataType.INTEGER, required = false, defaultValue = "30", defaultDisplay = false) Integer waitTimeout,
            @Argument(name = "text", comment = "文本", scope = ParamScope.ARGS, type = DataType.STRING) String text,
            @Argument(name = "swipe", scope = ParamScope.ARGS, comment = "滑动方向", type = DataType.ENUM, enumValues = SwipeDirection.class, inputType = InputType.select, defaultValue = "0", required = false, defaultDisplay = false) String swipe,
            @Argument(name = "swipeCount", scope = ParamScope.ARGS, comment = "滑动次数", type = DataType.INTEGER, defaultValue = "0", required = false, defaultDisplay = false) Integer swipeCount,
            @Argument(name = "value", scope = ParamScope.OUTPUT, comment = "组件返回值", type = DataType.STRING, defaultValue = "") String value,
            @Argument(name = "preExecuteWait", scope = ParamScope.ARGS, comment = "执行前等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float preExecuteWait,
            @Argument(name = "sufExecuteWait", scope = ParamScope.ARGS, comment = "执行后等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float sufExecuteWait
    ) {
        IfTextThread ifTextThread = new IfTextThread(context,deviceDriver,waitTimeout,swipe,swipeCount,preExecuteWait,sufExecuteWait,text);
        Future<Boolean> future = executorService.submit(ifTextThread);
        Boolean aBoolean = false;
        deviceDriver.setFuture(future);
        try {
            aBoolean = future.get(waitTimeout, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            logger.warn("该线程被中断了。。。。。。");
            throw new ExecuteException("执行中断");
        } catch (ExecutionException e) {
            logger.warn("在执行的时候报错了。。。。");
            Throwable cause = e.getCause();
            if (cause instanceof ExecuteException) {
                ExecuteException ee = (ExecuteException) cause;
                throw ee;
            } else if (cause instanceof ParamMistakeException) {
                ParamMistakeException pe = (ParamMistakeException) cause;
                throw pe;
            } else if (cause instanceof NoSuchSessionException) {
                NoSuchSessionException ne = (NoSuchSessionException) cause;
                throw ne;
            } else if (cause instanceof EnvironmentException) {
                EnvironmentException ee = (EnvironmentException) cause;
                throw ee;
            }else if (cause instanceof StaleElementReferenceException) {
                throw new ExecuteException("当前操作的元素已经失效");
            } else {
                logger.error("出现了其他的问题。。。。", e);
                throw new ExecuteException(cause.getMessage());
            }
        } catch (TimeoutException e) {
            logger.warn("处理超时了。。。。。。");
        } catch (CancellationException e) {
            logger.warn("该操作被取消了");
            throw new ExecuteException("用户取消，执行失败");
        }
        setParamValue(context, value, aBoolean.toString());
        return aBoolean;
    }

    /**
     * <p>点击控件</p>
     *
     * @param deviceDriver   设备驱动链接
     * @param targets        定位控件的信息
     * @param waitTimeout    默认超时时间
     * @param waitStatusStr  是否等待界面稳定
     * @param swipe          滑动方向
     * @param swipeCount     滑动次数
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    @Keyword(alias = "点击控件", category = "0", attributes = "45", commonlyUse = true)
    @Return(name = "result", comment = "点击结果", type = DataType.BOOLEAN)
    public boolean clickElement(IExecuteContext context,
                                @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver,
                                @Argument(name = "targets", scope = ParamScope.STEP, comment = "控件位置", type = DataType.LIST, defaultDisplay = false) List<IStepTarget> targets,
                                @Argument(name = "timeout", scope = ParamScope.ARGS, comment = "默认超时时间", type = DataType.INTEGER, required = false, defaultValue = "30", defaultDisplay = false) Integer waitTimeout,
                                @Argument(name = "waitStatus", scope = ParamScope.ARGS, comment = "等待界面稳定", type = DataType.ENUM, enumValues = WhetherOrNotEnum.class, inputType = InputType.select, defaultValue = "1", defaultDisplay = false) String waitStatusStr,
                                @Argument(name = "swipe", scope = ParamScope.ARGS, comment = "滑动方向", type = DataType.ENUM, enumValues = SwipeDirection.class, required = false, defaultValue = "0", inputType = InputType.select, defaultDisplay = false) String swipe,
                                @Argument(name = "swipeCount", scope = ParamScope.ARGS, comment = "滑动次数", type = DataType.INTEGER, required = false, defaultValue = "0", defaultDisplay = false) Integer swipeCount,
                                @Argument(name = "xMove", scope = ParamScope.ARGS, comment = "水平偏移量", type = DataType.INTEGER, required = false, defaultValue = "0", defaultDisplay = false) Integer xMove,
                                @Argument(name = "yMove", scope = ParamScope.ARGS, comment = "垂直偏移量", type = DataType.INTEGER, required = false, defaultValue = "0", defaultDisplay = false) Integer yMove,
                                @Argument(name = "preExecuteWait", scope = ParamScope.ARGS, comment = "执行前等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float preExecuteWait,
                                @Argument(name = "sufExecuteWait", scope = ParamScope.ARGS, comment = "执行后等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float sufExecuteWait
    ) {

        ClickElementThread clickElementThread = new ClickElementThread(context,deviceDriver,targets,waitTimeout,waitStatusStr,swipe,swipeCount,preExecuteWait,sufExecuteWait,xMove,yMove);
        Future<Boolean> future = executorService.submit(clickElementThread);
        Boolean aBoolean = null;
        deviceDriver.setFuture(future);
        try {
            aBoolean = future.get(waitTimeout, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            logger.warn("该线程被中断了。。。。。。");
            throw new ExecuteException("执行中断");
        } catch (ExecutionException e) {
            logger.warn("在执行的时候报错了。。。。");
            Throwable cause = e.getCause();
            if (cause instanceof ExecuteException) {
                ExecuteException ee = (ExecuteException) cause;
                throw ee;
            } else if (cause instanceof ParamMistakeException) {
                ParamMistakeException pe = (ParamMistakeException) cause;
                throw pe;
            } else if (cause instanceof NoSuchSessionException) {
                NoSuchSessionException ne = (NoSuchSessionException) cause;
                throw ne;
            } else if (cause instanceof EnvironmentException) {
                EnvironmentException ee = (EnvironmentException) cause;
                throw ee;
            } else if (cause instanceof StaleElementReferenceException) {
                throw new ExecuteException("当前操作的元素已经失效");
            } else {
                logger.error("出现了其他的问题。。。。", e);
                throw new ExecuteException(cause.getMessage());
            }
        } catch (TimeoutException e) {
            logger.warn("处理超时了。。。。。。");
            throw new ExecuteException("查找元素超时");
        } catch (CancellationException e) {
            logger.warn("该操作被取消了");
            throw new ExecuteException("用户取消，执行失败");
        }
        return aBoolean;
    }

    /**
     * <p>判断是否界面上存在某一个元素</p>
     *
     * @param deviceDriver   设备驱动
     * @param targets        元素的信息
     * @param waitTimeout    默认超时时间
     * @param waitStatusStr  是否等待界面稳定
     * @param swipe          滑动方向
     * @param swipeCount     滑动次数
     * @param value          返回结果接受的值
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    @Keyword(alias = "是否存在元素", category = "0", attributes = "45")
    @Return(name = "result", comment = "是否存在元素的结果", type = DataType.BOOLEAN)
    public boolean ifElement(IExecuteContext context,
                             @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver,
                             @Argument(name = "targets", scope = ParamScope.STEP, comment = "控件位置", type = DataType.LIST, defaultDisplay = false) List<IStepTarget> targets,
                             @Argument(name = "timeout", scope = ParamScope.ARGS, comment = "默认超时时间", type = DataType.INTEGER, required = false, defaultValue = "30", defaultDisplay = false) Integer waitTimeout,
                             @Argument(name = "waitStatus", scope = ParamScope.ARGS, comment = "等待界面稳定", type = DataType.ENUM, enumValues = WhetherOrNotEnum.class, inputType = InputType.select, defaultValue = "1", defaultDisplay = false) String waitStatusStr,
                             @Argument(name = "swipe", scope = ParamScope.ARGS, comment = "滑动方向", type = DataType.ENUM, enumValues = SwipeDirection.class, inputType = InputType.select, defaultValue = "0", required = false, defaultDisplay = false) String swipe,
                             @Argument(name = "swipeCount", scope = ParamScope.ARGS, comment = "滑动次数", type = DataType.INTEGER, defaultValue = "0", required = false, defaultDisplay = false) Integer swipeCount,
                             @Argument(name = "value", scope = ParamScope.OUTPUT, comment = "组件返回值", type = DataType.STRING, defaultValue = "") String value,
                             @Argument(name = "preExecuteWait", scope = ParamScope.ARGS, comment = "执行前等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float preExecuteWait,
                             @Argument(name = "sufExecuteWait", scope = ParamScope.ARGS, comment = "执行后等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float sufExecuteWait) {

        IfElementThread ifElementThread = new IfElementThread(context,deviceDriver,targets,waitTimeout,waitStatusStr,swipe,swipeCount,preExecuteWait,sufExecuteWait);
        Future<Boolean> future = executorService.submit(ifElementThread);
        Boolean aBoolean = false;
        deviceDriver.setFuture(future);
        try {
            aBoolean = future.get(waitTimeout, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            logger.warn("该线程被中断了。。。。。。");
            throw new ExecuteException("执行中断");
        } catch (ExecutionException e) {
            logger.warn("在执行的时候报错了。。。。");
            Throwable cause = e.getCause();
            if (cause instanceof ExecuteException) {
                ExecuteException ee = (ExecuteException) cause;
                throw ee;
            } else if (cause instanceof ParamMistakeException) {
                ParamMistakeException pe = (ParamMistakeException) cause;
                throw pe;
            } else if (cause instanceof NoSuchSessionException) {
                NoSuchSessionException ne = (NoSuchSessionException) cause;
                throw ne;
            } else if (cause instanceof EnvironmentException) {
                EnvironmentException ee = (EnvironmentException) cause;
                throw ee;
            }else if (cause instanceof StaleElementReferenceException) {
                throw new ExecuteException("当前操作的元素已经失效");
            } else {
                logger.error("出现了其他的问题。。。。", e);
                throw new ExecuteException(cause.getMessage());
            }
        } catch (TimeoutException e) {
            logger.warn("处理超时了。。。。。。");
        } catch (CancellationException e) {
            logger.warn("该操作被取消了");
            throw new ExecuteException("用户取消，执行失败");
        }
        setParamValue(context, value, aBoolean.toString());
        return aBoolean;
    }


    /**
     * <p>标准滑动屏幕</p>
     *
     * @param direction      滑动方向
     * @param deviceDriver   设备连接
     * @param size           滑动距离
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    @Keyword(alias = "标准滑动", category = "0", attributes = "45", commonlyUse = true)
    @Return(name = "result", comment = "滑动结果", type = DataType.BOOLEAN)
    public boolean standardSwipe(
            @Argument(name = "direction", scope = ParamScope.ARGS, comment = "滑动方向", type = DataType.ENUM, enumValues = SwipeDirection.class, inputType = InputType.select, defaultValue = "up") String direction,
            @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver,
            @Argument(name = "size", scope = ParamScope.ARGS, comment = "滑动距离", type = DataType.INTEGER, required = false, notNull = false, defaultValue = "500") Integer size,
            @Argument(name = "preExecuteWait", scope = ParamScope.ARGS, comment = "执行前等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float preExecuteWait,
            @Argument(name = "sufExecuteWait", scope = ParamScope.ARGS, comment = "执行后等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float sufExecuteWait
    ) {
        StandardSwipeThread ifElementThread = new StandardSwipeThread(deviceDriver,direction,size,preExecuteWait,sufExecuteWait);
        Future<Boolean> future = executorService.submit(ifElementThread);
        Boolean aBoolean = null;
        deviceDriver.setFuture(future);
        try {
            aBoolean = future.get(60, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            logger.warn("该线程被中断了。。。。。。");
            throw new ExecuteException("执行中断");
        } catch (ExecutionException e) {
            logger.warn("在执行的时候报错了。。。。");
            Throwable cause = e.getCause();
            if (cause instanceof ExecuteException) {
                ExecuteException ee = (ExecuteException) cause;
                throw ee;
            } else if (cause instanceof ParamMistakeException) {
                ParamMistakeException pe = (ParamMistakeException) cause;
                throw pe;
            } else if (cause instanceof NoSuchSessionException) {
                NoSuchSessionException ne = (NoSuchSessionException) cause;
                throw ne;
            } else if (cause instanceof EnvironmentException) {
                EnvironmentException ee = (EnvironmentException) cause;
                throw ee;
            }else if (cause instanceof StaleElementReferenceException) {
                throw new ExecuteException("当前操作的元素已经失效");
            } else {
                logger.error("出现了其他的问题。。。。", e);
                throw new ExecuteException(cause.getMessage());
            }
        } catch (TimeoutException e) {
            logger.warn("处理超时了。。。。。。");
            throw new ExecuteException("滑动屏幕超时");
        } catch (CancellationException e) {
            logger.warn("该操作被取消了");
            throw new ExecuteException("用户取消，执行失败");
        }
        return aBoolean;
    }

    /**
     * <p>控件滑动，以控件的中心坐标点为起点滑动</p>
     *
     * @param direction      滑动方向
     * @param deviceDriver   设备驱动
     * @param size           滑动距离
     * @param targets        控件信息
     * @param waitTimeout    默认超时时间
     * @param waitStatusStr  是否等待界面稳定
     * @param swipe          滑动方向
     * @param swipeCount     滑动次数
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    @Keyword(alias = "控件滑动", category = "0", attributes = "45", commonlyUse = true)
    @Return(name = "result", comment = "滑动的结果", type = DataType.BOOLEAN)
    public boolean elementSwipe(IExecuteContext context,
                                @Argument(name = "direction", scope = ParamScope.ARGS, comment = "控件滑动方向", type = DataType.ENUM, enumValues = SwipeDirection.class, defaultDisplay = false, inputType = InputType.select, defaultValue = "up") String direction,
                                @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver,
                                @Argument(name = "size", scope = ParamScope.ARGS, comment = "滑动距离", type = DataType.INTEGER, required = false, notNull = false, defaultValue = "500") Integer size,
                                @Argument(name = "targets", scope = ParamScope.STEP, comment = "控件位置", type = DataType.LIST, defaultDisplay = false) List<IStepTarget> targets,
                                @Argument(name = "timeout", scope = ParamScope.ARGS, comment = "默认超时时间", type = DataType.INTEGER, required = false, defaultValue = "30", defaultDisplay = false) Integer waitTimeout,
                                @Argument(name = "waitStatus", scope = ParamScope.ARGS, comment = "等待界面稳定", type = DataType.ENUM, enumValues = WhetherOrNotEnum.class, inputType = InputType.select, defaultValue = "1", defaultDisplay = false) String waitStatusStr,
                                @Argument(name = "swipe", scope = ParamScope.ARGS, comment = "查找控件滑动方向", type = DataType.ENUM, enumValues = SwipeDirection.class, inputType = InputType.select, defaultValue = "0", required = false, defaultDisplay = false) String swipe,
                                @Argument(name = "swipeCount", scope = ParamScope.ARGS, comment = "滑动次数", type = DataType.INTEGER, defaultValue = "0", required = false, defaultDisplay = false) Integer swipeCount,
                                @Argument(name = "preExecuteWait", scope = ParamScope.ARGS, comment = "执行前等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float preExecuteWait,
                                @Argument(name = "sufExecuteWait", scope = ParamScope.ARGS, comment = "执行后等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float sufExecuteWait) {
        ElementSwipeThread elementSwipeThread = new ElementSwipeThread(context,deviceDriver,targets,waitTimeout,waitStatusStr,swipe,swipeCount,preExecuteWait,sufExecuteWait,direction,size);
        Future<Boolean> future = executorService.submit(elementSwipeThread);
        Boolean aBoolean = null;
        deviceDriver.setFuture(future);
        try {
            aBoolean = future.get(waitTimeout, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            logger.warn("该线程被中断了。。。。。。");
            throw new ExecuteException("执行中断");
        } catch (ExecutionException e) {
            logger.warn("在执行的时候报错了。。。。");
            Throwable cause = e.getCause();
            if (cause instanceof ExecuteException) {
                ExecuteException ee = (ExecuteException) cause;
                throw ee;
            } else if (cause instanceof ParamMistakeException) {
                ParamMistakeException pe = (ParamMistakeException) cause;
                throw pe;
            } else if (cause instanceof NoSuchSessionException) {
                NoSuchSessionException ne = (NoSuchSessionException) cause;
                throw ne;
            } else if (cause instanceof EnvironmentException) {
                EnvironmentException ee = (EnvironmentException) cause;
                throw ee;
            }else if (cause instanceof StaleElementReferenceException) {
                throw new ExecuteException("当前操作的元素已经失效");
            } else {
                logger.error("出现了其他的问题。。。。", e);
                throw new ExecuteException(cause.getMessage());
            }
        } catch (TimeoutException e) {
            logger.warn("处理超时了。。。。。。");
            throw new ExecuteException("查找元素超时");
        } catch (CancellationException e) {
            logger.warn("该操作被取消了");
            throw new ExecuteException("用户取消，执行失败");
        }
        return aBoolean;
    }

    /**
     * <p>在控件中输入文本</p>
     *
     * @param text           输入的文本
     * @param cleanStr       是否清空文本框0-否，1-是
     * @param deviceDriver   设备连接驱动
     * @param targets        定位控件参数
     * @param waitTimeout    超时时间
     * @param waitStatusStr  是否等待屏幕稳定
     * @param swipe          是否滑屏查找控件0-否，up-上滑，down-下滑，left-左滑,right-右滑
     * @param swipeCount     滑屏次数
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    /*@Keyword(alias = "输入文本", category = "0", attributes = "4", commonlyUse = true)
    @Return(name = "result", comment = "输入的结果", type = DataType.BOOLEAN)
    public boolean inputText(IExecuteContext context,
                             @Argument(name = "text", scope = ParamScope.VARIABLES, comment = "输入的文本", type = DataType.STRING) String text,
                             @Argument(name = "clean", scope = ParamScope.ARGS, comment = "是否清空输入框", type = DataType.ENUM, enumValues = WhetherOrNotEnum.class, inputType = InputType.select, defaultValue = "1", defaultDisplay = false) String cleanStr,
                             @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver,
                             @Argument(name = "targets", scope = ParamScope.STEP, comment = "控件位置", type = DataType.LIST, defaultDisplay = false) List<IStepTarget> targets,
                             @Argument(name = "timeout", scope = ParamScope.ARGS, comment = "默认超时时间", type = DataType.INTEGER, required = false, defaultValue = "30", defaultDisplay = false) Integer waitTimeout,
                             @Argument(name = "waitStatus", scope = ParamScope.ARGS, comment = "等待界面稳定", type = DataType.ENUM, enumValues = WhetherOrNotEnum.class, inputType = InputType.select, defaultValue = "1", defaultDisplay = false) String waitStatusStr,
                             @Argument(name = "swipe", scope = ParamScope.ARGS, comment = "滑动方向", type = DataType.ENUM, enumValues = SwipeDirection.class, inputType = InputType.select, defaultValue = "0", required = false, defaultDisplay = false) String swipe,
                             @Argument(name = "swipeCount", scope = ParamScope.ARGS, comment = "滑动次数", type = DataType.INTEGER, required = false, defaultValue = "0", defaultDisplay = false) Integer swipeCount,

                             @Argument(name = "preExecuteWait", scope = ParamScope.ARGS, comment = "执行前等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float preExecuteWait,
                             @Argument(name = "sufExecuteWait", scope = ParamScope.ARGS, comment = "执行后等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float sufExecuteWait
    ) {

        InputTextThread inputTextThread = new InputTextThread(context,deviceDriver,targets,waitTimeout,waitStatusStr,swipe,swipeCount,preExecuteWait,sufExecuteWait,cleanStr,text);
        Future<Boolean> future = executorService.submit(inputTextThread);
        Boolean aBoolean = null;
        deviceDriver.setFuture(future);
        try {
            aBoolean = future.get(waitTimeout, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            logger.warn("该线程被中断了。。。。。。");
            throw new ExecuteException("执行中断");
        } catch (ExecutionException e) {
            logger.warn("在执行的时候报错了。。。。");
            Throwable cause = e.getCause();
            if (cause instanceof ExecuteException) {
                ExecuteException ee = (ExecuteException) cause;
                throw ee;
            } else if (cause instanceof ParamMistakeException) {
                ParamMistakeException pe = (ParamMistakeException) cause;
                throw pe;
            } else if (cause instanceof NoSuchSessionException) {
                NoSuchSessionException ne = (NoSuchSessionException) cause;
                throw ne;
            } else if (cause instanceof EnvironmentException) {
                EnvironmentException ee = (EnvironmentException) cause;
                throw ee;
            }else{
                logger.error("出现了其他的问题。。。。");
                throw new ExecuteException(cause.getMessage());
            }
        } catch (TimeoutException e) {
            logger.warn("处理超时了。。。。。。");
            throw new ExecuteException("查找元素超时");
        } catch (CancellationException e) {
            logger.warn("该操作被取消了");
            throw new ExecuteException("用户取消，执行失败");
        }
        return aBoolean;
    }*/

    /**
     * <p>在控件中输入文本</p>
     *
     * @param text           输入的文本
     * @param cleanStr       是否清空文本框0-否，1-是
     * @param deviceDriver   设备连接驱动
     * @param targets        定位控件参数
     * @param waitTimeout    超时时间
     * @param waitStatusStr  是否等待屏幕稳定
     * @param swipe          是否滑屏查找控件0-否，up-上滑，down-下滑，left-左滑,right-右滑
     * @param swipeCount     滑屏次数
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    @Keyword(alias = "控件输入文本", category = "0", attributes = "45", commonlyUse = true)
    @Return(name = "result", comment = "输入的结果", type = DataType.BOOLEAN)
    public boolean inputText(IExecuteContext context,
                             @Argument(name = "text", scope = ParamScope.VARIABLES, comment = "输入的文本", type = DataType.STRING) String text,
                             @Argument(name = "clean", scope = ParamScope.ARGS, comment = "是否清空输入框", type = DataType.ENUM, enumValues = WhetherOrNotEnum.class, inputType = InputType.select, defaultValue = "1", defaultDisplay = false) String cleanStr,
                             @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver,
                             @Argument(name = "targets", scope = ParamScope.STEP, comment = "控件位置", type = DataType.LIST, defaultDisplay = false) List<IStepTarget> targets,
                             @Argument(name = "timeout", scope = ParamScope.ARGS, comment = "默认超时时间", type = DataType.INTEGER, required = false, defaultValue = "30", defaultDisplay = false) Integer waitTimeout,
                             @Argument(name = "waitStatus", scope = ParamScope.ARGS, comment = "等待界面稳定", type = DataType.ENUM, enumValues = WhetherOrNotEnum.class, inputType = InputType.select, defaultValue = "1", defaultDisplay = false) String waitStatusStr,
                             @Argument(name = "swipe", scope = ParamScope.ARGS, comment = "滑动方向", type = DataType.ENUM, enumValues = SwipeDirection.class, inputType = InputType.select, defaultValue = "0", required = false, defaultDisplay = false) String swipe,
                             @Argument(name = "swipeCount", scope = ParamScope.ARGS, comment = "滑动次数", type = DataType.INTEGER, required = false, defaultValue = "0", defaultDisplay = false) Integer swipeCount,
                             @Argument(name = "preExecuteWait", scope = ParamScope.ARGS, comment = "执行前等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float preExecuteWait,
                             @Argument(name = "sufExecuteWait", scope = ParamScope.ARGS, comment = "执行后等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float sufExecuteWait
    ) {

        InputTextElementThread inputTextElementThread = new InputTextElementThread(context,deviceDriver,targets,waitTimeout,waitStatusStr,swipe,swipeCount,preExecuteWait,sufExecuteWait,cleanStr,text);
        Future<Boolean> future = executorService.submit(inputTextElementThread);
        Boolean aBoolean = null;
        deviceDriver.setFuture(future);
        try {
            aBoolean = future.get(waitTimeout, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            logger.warn("该线程被中断了。。。。。。");
            throw new ExecuteException("执行中断");
        } catch (ExecutionException e) {
            logger.warn("在执行的时候报错了。。。。");
            Throwable cause = e.getCause();
            if (cause instanceof ExecuteException) {
                ExecuteException ee = (ExecuteException) cause;
                throw ee;
            } else if (cause instanceof ParamMistakeException) {
                ParamMistakeException pe = (ParamMistakeException) cause;
                throw pe;
            } else if (cause instanceof NoSuchSessionException) {
                NoSuchSessionException ne = (NoSuchSessionException) cause;
                throw ne;
            } else if (cause instanceof EnvironmentException) {
                EnvironmentException ee = (EnvironmentException) cause;
                throw ee;
            }else if (cause instanceof StaleElementReferenceException) {
                throw new ExecuteException("当前操作的元素已经失效");
            } else {
                logger.error("出现了其他的问题。。。。", e);
                throw new ExecuteException(cause.getMessage());
            }
        } catch (TimeoutException e) {
            logger.warn("处理超时了。。。。。。");
            throw new ExecuteException("查找元素超时");
        } catch (CancellationException e) {
            logger.warn("该操作被取消了");
            throw new ExecuteException("用户取消，执行失败");
        }
        return aBoolean;
    }


    /**
     * <p>获取控件的值</p>
     *
     * @param deviceDriver   设备连接驱动
     * @param targets        定位控件参数
     * @param waitTimeout    超时时间
     * @param waitStatusStr  是否等待屏幕稳定
     * @param swipe          是否滑屏查找控件0-否，up-上滑，down-下滑，left-左滑,right-右滑
     * @param swipeCount     滑屏次数
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @param value          输出值
     * @return
     */
    @Keyword(alias = "获取控件的值", category = "0", attributes = "45")
    @Return(name = "result", comment = "输入的结果", type = DataType.OBJECT)
    public String getElementText(IExecuteContext context,
                                 @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver,
                                 @Argument(name = "targets", scope = ParamScope.STEP, comment = "控件位置", type = DataType.LIST, defaultDisplay = false) List<IStepTarget> targets,
                                 @Argument(name = "timeout", scope = ParamScope.ARGS, comment = "默认超时时间", type = DataType.INTEGER, required = false, defaultValue = "30", defaultDisplay = false) Integer waitTimeout,
                                 @Argument(name = "waitStatus", scope = ParamScope.ARGS, comment = "等待界面稳定", type = DataType.ENUM, enumValues = WhetherOrNotEnum.class, inputType = InputType.select, defaultValue = "1", defaultDisplay = false) String waitStatusStr,
                                 @Argument(name = "swipe", scope = ParamScope.ARGS, comment = "滑动方向", type = DataType.ENUM, enumValues = SwipeDirection.class, inputType = InputType.select, defaultValue = "0", required = false, defaultDisplay = false) String swipe,
                                 @Argument(name = "swipeCount", scope = ParamScope.ARGS, comment = "滑动次数", type = DataType.INTEGER, required = false, defaultValue = "0", defaultDisplay = false) Integer swipeCount,
                                 @Argument(name = "value", scope = ParamScope.OUTPUT, comment = "组件返回值", type = DataType.STRING, defaultValue = "") String value,
                                 @Argument(name = "preExecuteWait", scope = ParamScope.ARGS, comment = "执行前等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float preExecuteWait,
                                 @Argument(name = "sufExecuteWait", scope = ParamScope.ARGS, comment = "执行后等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float sufExecuteWait) {
        GetElementTextThread getElementTextThread = new GetElementTextThread(context,deviceDriver,targets,waitTimeout,waitStatusStr,swipe,swipeCount,preExecuteWait,sufExecuteWait);
        Future<String> future = executorService.submit(getElementTextThread);
        String result = null;
        deviceDriver.setFuture(future);
        try {
            result = future.get(waitTimeout, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            logger.warn("该线程被中断了。。。。。。");
            throw new ExecuteException("执行中断");
        } catch (ExecutionException e) {
            logger.warn("在执行的时候报错了。。。。");
            Throwable cause = e.getCause();
            if (cause instanceof ExecuteException) {
                ExecuteException ee = (ExecuteException) cause;
                throw ee;
            } else if (cause instanceof ParamMistakeException) {
                ParamMistakeException pe = (ParamMistakeException) cause;
                throw pe;
            } else if (cause instanceof NoSuchSessionException) {
                NoSuchSessionException ne = (NoSuchSessionException) cause;
                throw ne;
            } else if (cause instanceof EnvironmentException) {
                EnvironmentException ee = (EnvironmentException) cause;
                throw ee;
            }else if (cause instanceof StaleElementReferenceException) {
                throw new ExecuteException("当前操作的元素已经失效");
            } else {
                logger.error("出现了其他的问题。。。。", e);
                throw new ExecuteException(cause.getMessage());
            }
        } catch (TimeoutException e) {
            logger.warn("处理超时了。。。。。。");
            throw new ExecuteException("查找元素超时");
        } catch (CancellationException e) {
            logger.warn("该操作被取消了");
            throw new ExecuteException("用户取消，执行失败");
        }
        setParamValue(context, value, result);
        return result;
    }


    /**
     * <p>长按控件</p>
     *
     * @param deviceDriver   设备连接驱动
     * @param targets        定位控件参数
     * @param waitTimeout    超时时间
     * @param waitStatusStr  是否等待屏幕稳定
     * @param swipe          是否滑屏查找控件0-否，up-上滑，down-下滑，left-左滑,right-右滑
     * @param swipeCount     滑屏次数
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    @Keyword(alias = "长按控件", category = "0", attributes = "45", commonlyUse = true)
    @Return(name = "result", comment = "输入的结果", type = DataType.BOOLEAN)
    public boolean longPress(IExecuteContext context,
                             @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver,
                             @Argument(name = "targets", scope = ParamScope.STEP, comment = "控件位置", type = DataType.LIST, defaultDisplay = false) List<IStepTarget> targets,
                             @Argument(name = "timeout", scope = ParamScope.ARGS, comment = "默认超时时间", type = DataType.INTEGER, required = false, defaultValue = "30", defaultDisplay = false) Integer waitTimeout,
                             @Argument(name = "waitStatus", scope = ParamScope.ARGS, comment = "等待界面稳定", type = DataType.ENUM, enumValues = WhetherOrNotEnum.class, inputType = InputType.select, defaultValue = "1", defaultDisplay = false) String waitStatusStr,
                             @Argument(name = "swipe", scope = ParamScope.ARGS, comment = "滑动方向", type = DataType.ENUM, enumValues = SwipeDirection.class, inputType = InputType.select, defaultValue = "0", required = false, defaultDisplay = false) String swipe,
                             @Argument(name = "swipeCount", scope = ParamScope.ARGS, comment = "滑动次数", type = DataType.INTEGER, defaultValue = "0", required = false, defaultDisplay = false) Integer swipeCount,
                             @Argument(name = "preExecuteWait", scope = ParamScope.ARGS, comment = "执行前等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float preExecuteWait,
                             @Argument(name = "sufExecuteWait", scope = ParamScope.ARGS, comment = "执行后等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float sufExecuteWait
    ) {
        LongPressThread longPressThread = new LongPressThread(context,deviceDriver,targets,waitTimeout,waitStatusStr,swipe,swipeCount,preExecuteWait,sufExecuteWait);
        Future<Boolean> future = executorService.submit(longPressThread);
        Boolean aBoolean = null;
        deviceDriver.setFuture(future);
        try {
            aBoolean = future.get(waitTimeout, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            logger.warn("该线程被中断了。。。。。。");
            throw new ExecuteException("执行中断");
        } catch (ExecutionException e) {
            logger.warn("在执行的时候报错了。。。。");
            Throwable cause = e.getCause();
            if (cause instanceof ExecuteException) {
                ExecuteException ee = (ExecuteException) cause;
                throw ee;
            } else if (cause instanceof ParamMistakeException) {
                ParamMistakeException pe = (ParamMistakeException) cause;
                throw pe;
            } else if (cause instanceof NoSuchSessionException) {
                NoSuchSessionException ne = (NoSuchSessionException) cause;
                throw ne;
            } else if (cause instanceof EnvironmentException) {
                EnvironmentException ee = (EnvironmentException) cause;
                throw ee;
            }else if (cause instanceof StaleElementReferenceException) {
                throw new ExecuteException("当前操作的元素已经失效");
            } else {
                logger.error("出现了其他的问题。。。。", e);
                throw new ExecuteException(cause.getMessage());
            }
        } catch (TimeoutException e) {
            logger.warn("处理超时了。。。。。。");
            throw new ExecuteException("查找元素超时");
        } catch (CancellationException e) {
            logger.warn("该操作被取消了");
            throw new ExecuteException("用户取消，执行失败");
        }
        return aBoolean;
    }

    /**
     * <p>断言元素</p>
     *
     * @param deviceDriver   设备连接驱动
     * @param targets        定位控件参数
     * @param waitTimeout    超时时间
     * @param waitStatusStr  是否等待屏幕稳定
     * @param swipe          是否滑屏查找控件0-否，up-上滑，down-下滑，left-左滑,right-右滑
     * @param swipeCount     滑屏次数
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    @Keyword(alias = "断言元素", category = "0", attributes = "45", commonlyUse = true)
    @Return(name = "result", comment = "断言结果", type = DataType.BOOLEAN)
    public boolean assertElement(IExecuteContext context,
                                 @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver,
                                 @Argument(name = "timeout", scope = ParamScope.ARGS, comment = "默认超时时间", type = DataType.INTEGER, required = false, defaultValue = "30", defaultDisplay = false) Integer waitTimeout,
                                 @Argument(name = "waitStatus", scope = ParamScope.ARGS, comment = "等待界面稳定", type = DataType.ENUM, enumValues = WhetherOrNotEnum.class, inputType = InputType.select, defaultValue = "1", defaultDisplay = false) String waitStatusStr,
                                 @Argument(name = "swipe", scope = ParamScope.ARGS, comment = "滑动方向", type = DataType.ENUM, enumValues = SwipeDirection.class, inputType = InputType.select, defaultValue = "0", required = false, defaultDisplay = false) String swipe,
                                 @Argument(name = "swipeCount", scope = ParamScope.ARGS, comment = "滑动次数", type = DataType.INTEGER, defaultValue = "0", required = false, defaultDisplay = false) Integer swipeCount,
                                 @Argument(name = "targets", scope = ParamScope.STEP, comment = "图片参数", type = DataType.LIST, defaultDisplay = false) List<IStepTarget> targets,
                                 @Argument(name = "preExecuteWait", scope = ParamScope.ARGS, comment = "执行前等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float preExecuteWait,
                                 @Argument(name = "sufExecuteWait", scope = ParamScope.ARGS, comment = "执行后等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float sufExecuteWait
    ) {
        AssertElementThread assertElementThread = new AssertElementThread(context,deviceDriver,targets,waitTimeout,waitStatusStr,swipe,swipeCount,preExecuteWait,sufExecuteWait);
        Future<Boolean> future = executorService.submit(assertElementThread);
        Boolean aBoolean = null;
        deviceDriver.setFuture(future);
        try {
            aBoolean = future.get(waitTimeout, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            logger.warn("该线程被中断了。。。。。。");
            throw new ExecuteException("执行中断");
        } catch (ExecutionException e) {
            logger.warn("在执行的时候报错了。。。。");
            Throwable cause = e.getCause();
            if (cause instanceof ExecuteException) {
                ExecuteException ee = (ExecuteException) cause;
                throw ee;
            } else if (cause instanceof ParamMistakeException) {
                ParamMistakeException pe = (ParamMistakeException) cause;
                throw pe;
            } else if (cause instanceof NoSuchSessionException) {
                NoSuchSessionException ne = (NoSuchSessionException) cause;
                throw ne;
            } else if (cause instanceof EnvironmentException) {
                EnvironmentException ee = (EnvironmentException) cause;
                throw ee;
            }else if (cause instanceof StaleElementReferenceException) {
                throw new ExecuteException("当前操作的元素已经失效");
            } else {
                logger.error("出现了其他的问题。。。。", e);
                throw new ExecuteException(cause.getMessage());
            }
        } catch (TimeoutException e) {
            logger.warn("处理超时了。。。。。。");
        } catch (CancellationException e) {
            logger.warn("该操作被取消了");
            throw new ExecuteException("用户取消，执行失败");
        }
        if (aBoolean != null && aBoolean) {
            return true;
        }
        throw new AssertException("断言失败，找不到目标元素");
    }

    /**
     * <p>app处理</p>
     *
     * @param deviceDriver   设备连接驱动
     * @param appPackage     启动包名
     * @param waitTimeout    等待超时时间
     * @param type           操作应用的类型0-关闭，1-启动
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    @Keyword(alias = "app处理", category = "0", attributes = "45", commonlyUse = true)
    @Return(name = "result", comment = "app处理", type = DataType.BOOLEAN)
    public boolean handleApp(IExecuteContext context,
                             @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver,
                             @Argument(name = "appPackage", scope = ParamScope.ARGS, comment = "应用包名", type = DataType.STRING) String appPackage,
                             @Argument(name = "timeout", scope = ParamScope.ARGS, comment = "默认超时时间", type = DataType.INTEGER, required = false, defaultValue = "30", defaultDisplay = false) Integer waitTimeout,
                             @Argument(name = "type", scope = ParamScope.ARGS, comment = "应用操作类型", type = DataType.ENUM, enumValues = AppEnum.class, inputType = InputType.select, defaultValue = "1") String type,
                             @Argument(name = "preExecuteWait", scope = ParamScope.ARGS, comment = "执行前等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float preExecuteWait,
                             @Argument(name = "sufExecuteWait", scope = ParamScope.ARGS, comment = "执行后等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float sufExecuteWait) {
        AppHandleThread appHandleThread = new AppHandleThread(context,deviceDriver,waitTimeout,appPackage,type,preExecuteWait,sufExecuteWait);
        Future<Boolean> future = executorService.submit(appHandleThread);
        Boolean aBoolean = null;
        deviceDriver.setFuture(future);
        try {
            aBoolean = future.get(waitTimeout, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            logger.warn("该线程被中断了。。。。。。");
            throw new ExecuteException("执行中断");
        } catch (ExecutionException e) {
            logger.warn("在执行的时候报错了。。。。");
            Throwable cause = e.getCause();
            if (cause instanceof ExecuteException) {
                ExecuteException ee = (ExecuteException) cause;
                throw ee;
            } else if (cause instanceof ParamMistakeException) {
                ParamMistakeException pe = (ParamMistakeException) cause;
                throw pe;
            } else if (cause instanceof NoSuchSessionException) {
                NoSuchSessionException ne = (NoSuchSessionException) cause;
                throw ne;
            } else if (cause instanceof EnvironmentException) {
                EnvironmentException ee = (EnvironmentException) cause;
                throw ee;
            }else if (cause instanceof StaleElementReferenceException) {
                throw new ExecuteException("当前操作的元素已经失效");
            } else {
                logger.error("出现了其他的问题。。。。", e);
                throw new ExecuteException(cause.getMessage());
            }
        } catch (TimeoutException e) {
            logger.warn("处理超时了。。。。。。");
            throw new ExecuteException("操作app超时");
        } catch (CancellationException e) {
            logger.warn("该操作被取消了");
            throw new ExecuteException("用户取消，执行失败");
        }
        return aBoolean;
    }

    /**
     * <p>点击home键</p>
     *
     * @param deviceDriver   设备连接驱动
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    @Keyword(alias = "点击home键", category = "0", attributes = "45", commonlyUse = true)
    @Return(name = "result", comment = "点击home键", type = DataType.BOOLEAN)
    public boolean pressKeyHome(IExecuteContext context,
                                @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver,
                                @Argument(name = "preExecuteWait", scope = ParamScope.ARGS, comment = "执行前等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float preExecuteWait,
                                @Argument(name = "sufExecuteWait", scope = ParamScope.ARGS, comment = "执行后等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float sufExecuteWait) {
        PressKeyHomeThread pressKeyHomeThread = new PressKeyHomeThread(context,deviceDriver,preExecuteWait,sufExecuteWait);
        Future<Boolean> future = executorService.submit(pressKeyHomeThread);
        Boolean aBoolean = null;
        deviceDriver.setFuture(future);
        try {
            aBoolean = future.get(30, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            logger.warn("该线程被中断了。。。。。。");
            throw new ExecuteException("执行中断");
        } catch (ExecutionException e) {
            logger.warn("在执行的时候报错了。。。。");
            Throwable cause = e.getCause();
            if (cause instanceof ExecuteException) {
                ExecuteException ee = (ExecuteException) cause;
                throw ee;
            } else if (cause instanceof ParamMistakeException) {
                ParamMistakeException pe = (ParamMistakeException) cause;
                throw pe;
            } else if (cause instanceof NoSuchSessionException) {
                NoSuchSessionException ne = (NoSuchSessionException) cause;
                throw ne;
            } else if (cause instanceof EnvironmentException) {
                EnvironmentException ee = (EnvironmentException) cause;
                throw ee;
            }else if (cause instanceof StaleElementReferenceException) {
                throw new ExecuteException("当前操作的元素已经失效");
            } else {
                logger.error("出现了其他的问题。。。。", e);
                throw new ExecuteException(cause.getMessage());
            }
        } catch (TimeoutException e) {
            logger.warn("处理超时了。。。。。。");
            throw new ExecuteException("点击home键超时");
        } catch (CancellationException e) {
            logger.warn("该操作被取消了");
            throw new ExecuteException("用户取消，执行失败");
        }
        return aBoolean;
    }


    /**
     * <p>验证码识别</p>
     *
     * @param deviceDriver   设备连接驱动
     * @param targets        定位元素参数
     * @param waitTimeout    等待超时时间
     * @param value          赋值变量
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    @Keyword(alias = "识别验证码", category = "0", attributes = "45")
    @Return(name = "result", comment = "验证码识别", type = DataType.STRING)
    public String getCodeByOcr(
            IExecuteContext context,
            @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver,
            @Argument(name = "targets", scope = ParamScope.STEP, comment = "控件位置", type = DataType.LIST, defaultDisplay = false) List<IStepTarget> targets,
            @Argument(name = "timeout", scope = ParamScope.ARGS, comment = "默认超时时间", type = DataType.INTEGER, required = false, defaultValue = "30", defaultDisplay = false) Integer waitTimeout,
            @Argument(name = "value", scope = ParamScope.OUTPUT, comment = "组件返回值", type = DataType.STRING, defaultValue = "") String value,
            @Argument(name = "waitStatus", scope = ParamScope.ARGS, comment = "等待界面稳定", type = DataType.ENUM, enumValues = WhetherOrNotEnum.class, inputType = InputType.select, defaultValue = "1", defaultDisplay = false) String waitStatusStr,
            @Argument(name = "preExecuteWait", scope = ParamScope.ARGS, comment = "执行前等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float preExecuteWait,
            @Argument(name = "sufExecuteWait", scope = ParamScope.ARGS, comment = "执行后等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float sufExecuteWait

    ) {
        GetCodeByOcrThread getCodeByOcrThread = new GetCodeByOcrThread(context,deviceDriver,targets,waitTimeout,waitStatusStr,preExecuteWait,sufExecuteWait);
        Future<String> future = executorService.submit(getCodeByOcrThread);
        String result = null;
        deviceDriver.setFuture(future);
        try {
            result = future.get(30, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            logger.warn("该线程被中断了。。。。。。");
            throw new ExecuteException("执行中断");
        } catch (ExecutionException e) {
            logger.warn("在执行的时候报错了。。。。");
            Throwable cause = e.getCause();
            if (cause instanceof ExecuteException) {
                ExecuteException ee = (ExecuteException) cause;
                throw ee;
            } else if (cause instanceof ParamMistakeException) {
                ParamMistakeException pe = (ParamMistakeException) cause;
                throw pe;
            } else if (cause instanceof NoSuchSessionException) {
                NoSuchSessionException ne = (NoSuchSessionException) cause;
                throw ne;
            } else if (cause instanceof EnvironmentException) {
                EnvironmentException ee = (EnvironmentException) cause;
                throw ee;
            }else if (cause instanceof StaleElementReferenceException) {
                throw new ExecuteException("当前操作的元素已经失效");
            } else {
                logger.error("出现了其他的问题。。。。", e);
                throw new ExecuteException(cause.getMessage());
            }
        } catch (TimeoutException e) {
            logger.warn("处理超时了。。。。。。");
            throw new ExecuteException("查找元素超时");
        } catch (CancellationException e) {
            logger.warn("该操作被取消了");
            throw new ExecuteException("用户取消，执行失败");
        }
        setParamValue(context, value, result);
        return result;
    }



    /**
     * <p>monkey测试</p>
     *
     * @param deviceDriver        设备连接驱动
     * @param execNum             执行次数
     * @param packageName         包名
     * @param seed                随机种子
     * @param throttle            每次执行的间隔（单位ms）
     * @param touch               触摸时间百分比
     * @param montion             移动时间百分比
     * @param pinchroom           缩放事件百分比
     * @param trackball           滚动球时间百分比
     * @param ratation            屏幕旋转时间百分比
     * @param nav                 基本导航时间百分比
     * @param majornav            主要导航事件的百分比
     * @param syskeys             系统时间百分比
     * @param appswitch           activity启动的百分比
     * @param flip                键盘翻转时间百分比
     * @param anyevent            其他时间的百分比
     * @param ignoreCrashes       应用程序发生崩溃或者异常时，monkey是否停止
     * @param ignoreTimeouts      应用程序发生任何超时粗偶时，monkey是否停止
     * @param ignoreNativeCrashes 是否忽略monkey本身的异常
     * @param preExecuteWait      执行前等待
     * @param sufExecuteWait      执行后等待
     * @return
     */
    @Keyword(alias = "monkey测试", category = "0", attributes = "45")
    @Return(name = "result", comment = "验证码识别", type = DataType.BOOLEAN)
    public boolean monkeyTest(
            IExecuteContext context,
            @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver,
            @Argument(name = "execNum", scope = ParamScope.ARGS, comment = "执行次数", type = DataType.LONG, defaultValue = "30") Long execNum,
            @Argument(name = "packageName", scope = ParamScope.ARGS, comment = "测试包名", type = DataType.STRING, required = false, defaultDisplay = false, defaultValue = "") String packageName,
            @Argument(name = "seed", scope = ParamScope.ARGS, comment = "随机序列", type = DataType.INTEGER, required = false, defaultDisplay = false, defaultValue = "0") Integer seed,
            @Argument(name = "throttle", scope = ParamScope.ARGS, comment = "时间间隔", type = DataType.LONG, required = false, defaultDisplay = false, defaultValue = "300") Long throttle,
            @Argument(name = "touch", scope = ParamScope.ARGS, comment = "touch", type = DataType.INTEGER, required = false, defaultDisplay = false, defaultValue = "0") Integer touch,
            @Argument(name = "montion", scope = ParamScope.ARGS, comment = "montion", type = DataType.INTEGER, required = false, defaultDisplay = false, defaultValue = "0") Integer montion,
            @Argument(name = "pinchroom", scope = ParamScope.ARGS, comment = "pinchroom", type = DataType.INTEGER, required = false, defaultDisplay = false, defaultValue = "0") Integer pinchroom,
            @Argument(name = "trackball", scope = ParamScope.ARGS, comment = "trackball", type = DataType.INTEGER, required = false, defaultDisplay = false, defaultValue = "0") Integer trackball,
            @Argument(name = "ratation", scope = ParamScope.ARGS, comment = "ratation", type = DataType.INTEGER, required = false, defaultDisplay = false, defaultValue = "0") Integer ratation,
            @Argument(name = "nav", scope = ParamScope.ARGS, comment = "nav", type = DataType.INTEGER, required = false, defaultDisplay = false, defaultValue = "0") Integer nav,
            @Argument(name = "majornav", scope = ParamScope.ARGS, comment = "majornav", type = DataType.INTEGER, required = false, defaultDisplay = false, defaultValue = "0") Integer majornav,
            @Argument(name = "syskeys", scope = ParamScope.ARGS, comment = "syskeys", type = DataType.INTEGER, required = false, defaultDisplay = false, defaultValue = "0") Integer syskeys,
            @Argument(name = "appswitch", scope = ParamScope.ARGS, comment = "appswitch", type = DataType.INTEGER, required = false, defaultDisplay = false, defaultValue = "0") Integer appswitch,
            @Argument(name = "flip", scope = ParamScope.ARGS, comment = "flip", type = DataType.INTEGER, required = false, defaultDisplay = false, defaultValue = "0") Integer flip,
            @Argument(name = "anyevent", scope = ParamScope.ARGS, comment = "anyevent", type = DataType.INTEGER, required = false, defaultDisplay = false, defaultValue = "0") Integer anyevent,
            @Argument(name = "ignoreCrashes", scope = ParamScope.ARGS, comment = "ignoreCrashes", type = DataType.INTEGER, required = false, defaultDisplay = false, defaultValue = "0") Boolean ignoreCrashes,
            @Argument(name = "ignoreTimeouts", scope = ParamScope.ARGS, comment = "ignoreTimeouts", type = DataType.INTEGER, required = false, defaultDisplay = false, defaultValue = "0") Boolean ignoreTimeouts,
            @Argument(name = "ignoreNativeCrashes", scope = ParamScope.ARGS, comment = "ignoreNativeCrashes", type = DataType.INTEGER, required = false, defaultDisplay = false, defaultValue = "0") Boolean ignoreNativeCrashes,
            @Argument(name = "preExecuteWait", scope = ParamScope.ARGS, comment = "执行前等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float preExecuteWait,
            @Argument(name = "sufExecuteWait", scope = ParamScope.ARGS, comment = "执行后等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float sufExecuteWait
    ) {
        MonkeyTestThread monkeyTestThread = new MonkeyTestThread(context,deviceDriver,preExecuteWait,sufExecuteWait,execNum,packageName,seed,throttle,touch,montion,pinchroom,trackball,ratation,nav,majornav,syskeys,appswitch,flip,anyevent,ignoreCrashes,ignoreTimeouts,ignoreNativeCrashes);
        Future<Boolean> future = executorService.submit(monkeyTestThread);
        Boolean result = null;
        deviceDriver.setFuture(future);
        try {
            result = future.get(execNum * throttle + 5000, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            logger.warn("该线程被中断了。。。。。。");
            throw new ExecuteException("执行中断");
        } catch (ExecutionException e) {
            logger.warn("在执行的时候报错了。。。。");
            Throwable cause = e.getCause();
            if (cause instanceof ExecuteException) {
                ExecuteException ee = (ExecuteException) cause;
                throw ee;
            } else if (cause instanceof ParamMistakeException) {
                ParamMistakeException pe = (ParamMistakeException) cause;
                throw pe;
            } else if (cause instanceof NoSuchSessionException) {
                NoSuchSessionException ne = (NoSuchSessionException) cause;
                throw ne;
            } else if (cause instanceof EnvironmentException) {
                EnvironmentException ee = (EnvironmentException) cause;
                throw ee;
            }else if (cause instanceof StaleElementReferenceException) {
                throw new ExecuteException("当前操作的元素已经失效");
            } else {
                logger.error("出现了其他的问题。。。。", e);
                throw new ExecuteException(cause.getMessage());
            }
        } catch (TimeoutException e) {
            logger.warn("处理超时了。。。。。。");
            throw new ExecuteException("monkey测试超时");
        } catch (CancellationException e) {
            logger.warn("该操作被取消了");
            throw new ExecuteException("用户取消，执行失败");
        }
        return result;
    }

    /**
     * <p>等待</p>
     *
     * @param waitTime 等待时间（单位s）
     * @return
     */
    @Keyword(alias = "等待", category = "0", attributes = "45")
    @Return(name = "result", comment = "验证码识别", type = DataType.BOOLEAN)
    public boolean wait(
            @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver,
            @Argument(name = "waitTime", scope = ParamScope.ARGS, comment = "等待时间(单位s)", type = DataType.INTEGER, defaultValue = "3") Integer waitTime
    ) {
        WaitThread waitThread = new WaitThread(waitTime);
        Future<Boolean> future = executorService.submit(waitThread);
        Boolean result = null;
        deviceDriver.setFuture(future);
        try {
            long time = waitTime + 5L;
            result = future.get(time, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            logger.warn("该线程被中断了。。。。。。");
            throw new ExecuteException("执行中断");
        } catch (ExecutionException e) {
            logger.warn("在执行的时候报错了。。。。");
            Throwable cause = e.getCause();
            if (cause instanceof ExecuteException) {
                ExecuteException ee = (ExecuteException) cause;
                throw ee;
            } else if (cause instanceof ParamMistakeException) {
                ParamMistakeException pe = (ParamMistakeException) cause;
                throw pe;
            } else if (cause instanceof NoSuchSessionException) {
                NoSuchSessionException ne = (NoSuchSessionException) cause;
                throw ne;
            } else if (cause instanceof EnvironmentException) {
                EnvironmentException ee = (EnvironmentException) cause;
                throw ee;
            }else if (cause instanceof StaleElementReferenceException) {
                throw new ExecuteException("当前操作的元素已经失效");
            } else {
                logger.error("出现了其他的问题。。。。", e);
                throw new ExecuteException(cause.getMessage());
            }
        } catch (TimeoutException e) {
            logger.warn("处理超时了。。。。。。");
        } catch (CancellationException e) {
            logger.warn("该操作被取消了");
            throw new ExecuteException("用户取消，执行失败");
        }
        return result;
    }

    /**
     * <p>接口方式获取验证码（临时）</p>
     *
     * @return
     */
    @Keyword(alias = "接口方式获取验证码", category = "0", attributes = "45")
    @Return(name = "result", comment = "接口方式获取验证码", type = DataType.BOOLEAN)
    public String getCodeByHttp(
            IExecuteContext context,
            @Argument(name = "url", scope = ParamScope.ARGS, comment = "验证码获取地址", type = DataType.STRING) String url,
            @Argument(name = "header", scope = ParamScope.ARGS, comment = "请求头", type = DataType.STRING) String header,
            @Argument(name = "body", scope = ParamScope.ARGS, comment = "请求体", type = DataType.STRING) String body,
            @Argument(name = "value", scope = ParamScope.OUTPUT, comment = "组件返回值", type = DataType.STRING, defaultValue = "") String value,
            @Argument(name = "waitTime", scope = ParamScope.ARGS, comment = "等待时间(单位s)", type = DataType.INTEGER, defaultValue = "30") Integer waitTime
    ) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        if (StringUtils.hasText(header)) {
            Map map = JSON.parseObject(header, Map.class);
            for (Object o : map.keySet()) {
                headers.add((String) o, (String) map.get(o));
            }
        }
        String result = null;
        Map map = JSON.parseObject(body, Map.class);
        HttpEntity<Map> entity = new HttpEntity<>(map, headers);
        JSONObject data = HttpUtils.doPost(url, entity, JSONObject.class);
        JSONArray gridData = data.getJSONArray("gridData");
        if (gridData.size() > 0) {
            Object o = gridData.get(0);
            logger.info("获取验证码的数据：{}", JSON.toJSONString(o));
            JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(o), JSONObject.class);
            String psend = jsonObject.getString("psend");
            int index = psend.indexOf("</retdesc><responsecode>");
            result = psend.substring(index + 24, psend.lastIndexOf("</responsecode>"));
            logger.info("获取的验证码：{}", result);
        }
        setParamValue(context,value,result);
        return result;
    }

    @Keyword(alias = "模拟键盘输入", category = "0", attributes = "45")
    @Return(name = "result", comment = "模拟键盘输入", type = DataType.BOOLEAN)
    public Boolean inputFromKeyBoard(
            IExecuteContext context,
            @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver,
            @Argument(name = "keyCode", scope = ParamScope.ARGS, comment = "键盘码", type = DataType.ENUM, enumValues = KeyCode.class, inputType = InputType.select) int keyCode,
            @Argument(name = "waitTime", scope = ParamScope.ARGS, comment = "等待时间(单位s)", type = DataType.INTEGER, defaultValue = "30") Integer waitTime,
            @Argument(name = "preExecuteWait", scope = ParamScope.ARGS, comment = "执行前等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float preExecuteWait,
            @Argument(name = "sufExecuteWait", scope = ParamScope.ARGS, comment = "执行后等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float sufExecuteWait
    ) {
        InputFromKeyBoardThread monkeyTestThread = new InputFromKeyBoardThread(deviceDriver,keyCode,preExecuteWait,sufExecuteWait);
        Future<Boolean> future = executorService.submit(monkeyTestThread);
        Boolean result = null;
        deviceDriver.setFuture(future);
        try {
            long time = waitTime*1000L;
            result = future.get(time, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            logger.warn("该线程被中断了。。。。。。");
            throw new ExecuteException("执行中断");
        } catch (ExecutionException e) {
            logger.warn("在执行的时候报错了。。。。");
            Throwable cause = e.getCause();
            if (cause instanceof ExecuteException) {
                ExecuteException ee = (ExecuteException) cause;
                throw ee;
            } else if (cause instanceof ParamMistakeException) {
                ParamMistakeException pe = (ParamMistakeException) cause;
                throw pe;
            } else if (cause instanceof NoSuchSessionException) {
                NoSuchSessionException ne = (NoSuchSessionException) cause;
                throw ne;
            } else if (cause instanceof EnvironmentException) {
                EnvironmentException ee = (EnvironmentException) cause;
                throw ee;
            }else if (cause instanceof StaleElementReferenceException) {
                throw new ExecuteException("当前操作的元素已经失效");
            } else {
                logger.error("出现了其他的问题。。。。", e);
                throw new ExecuteException(cause.getMessage());
            }
        } catch (TimeoutException e) {
            logger.warn("处理超时了。。。。。。");
            throw new ExecuteException("输入超时");
        } catch (CancellationException e) {
            logger.warn("该操作被取消了");
            throw new ExecuteException("用户取消，执行失败");
        }
        return result;
    }

    @Keyword(alias = "输入密码", category = "0", attributes = "45")
    @Return(name = "result", comment = "输入密码", type = DataType.BOOLEAN)
    public Boolean inputPassword(
            IExecuteContext context,
            @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver,
            @Argument(name = "text", scope = ParamScope.VARIABLES, comment = "输入的密码", type = DataType.STRING) String text,
            @Argument(name = "timeout", scope = ParamScope.ARGS, comment = "默认超时时间", type = DataType.INTEGER, required = false, defaultValue = "30", defaultDisplay = false) Integer waitTimeout,
            @Argument(name = "preExecuteWait", scope = ParamScope.ARGS, comment = "执行前等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float preExecuteWait,
            @Argument(name = "sufExecuteWait", scope = ParamScope.ARGS, comment = "执行后等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "0.0", defaultDisplay = false) Float sufExecuteWait
    ) {
        InputPasswordThread inputPasswordThread = new InputPasswordThread(context,deviceDriver,preExecuteWait,sufExecuteWait,text);
        Future<Boolean> future = executorService.submit(inputPasswordThread);
        Boolean result = null;
        deviceDriver.setFuture(future);
        try {
            result = future.get(waitTimeout*1000L, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            logger.warn("该线程被中断了。。。。。。");
            throw new ExecuteException("执行中断");
        } catch (ExecutionException e) {
            logger.warn("在执行的时候报错了。。。。");
            Throwable cause = e.getCause();
            if (cause instanceof ExecuteException) {
                ExecuteException ee = (ExecuteException) cause;
                throw ee;
            } else if (cause instanceof ParamMistakeException) {
                ParamMistakeException pe = (ParamMistakeException) cause;
                throw pe;
            } else if (cause instanceof NoSuchSessionException) {
                NoSuchSessionException ne = (NoSuchSessionException) cause;
                throw ne;
            } else if (cause instanceof EnvironmentException) {
                EnvironmentException ee = (EnvironmentException) cause;
                throw ee;
            }else if (cause instanceof StaleElementReferenceException) {
                throw new ExecuteException("当前操作的元素已经失效");
            } else {
                logger.error("出现了其他的问题。。。。", e);
                throw new ExecuteException(cause.getMessage());
            }
        } catch (TimeoutException e) {
            logger.warn("处理超时了。。。。。。");
            throw new ExecuteException("输入超时");
        } catch (CancellationException e) {
            logger.warn("该操作被取消了");
            throw new ExecuteException("用户取消，执行失败");
        }
        return result;
    }

    /**
     * <p>点击控件</p>
     *
     * @param deviceDriver   设备驱动链接
     * @param targets        定位控件的信息
     * @param waitTimeout    默认超时时间
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    @Keyword(alias = "密码输入(ocr)", category = "0", attributes = "45", commonlyUse = true)
    @Return(name = "result", comment = "输入结果", type = DataType.BOOLEAN)
    public boolean inputPasswordByOcr(IExecuteContext context,
                                      @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver,
                                      @Argument(name = "text", scope = ParamScope.VARIABLES, comment = "输入的密码", type = DataType.STRING) String text,
                                      @Argument(name = "targets", scope = ParamScope.STEP, comment = "控件位置", type = DataType.LIST, defaultDisplay = false) List<IStepTarget> targets,
                                      @Argument(name = "timeout", scope = ParamScope.ARGS, comment = "默认超时时间", type = DataType.INTEGER, required = false, defaultValue = "30", defaultDisplay = false) Integer waitTimeout,
                                      @Argument(name = "preExecuteWait", scope = ParamScope.ARGS, comment = "执行前等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "1.0", defaultDisplay = false) Float preExecuteWait,
                                      @Argument(name = "sufExecuteWait", scope = ParamScope.ARGS, comment = "执行后等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "1.0", defaultDisplay = false) Float sufExecuteWait
    ) {
        InputPasswordThreadByOcrThread inputPasswordByOcr = new InputPasswordThreadByOcrThread(context,targets,deviceDriver,preExecuteWait,sufExecuteWait,text);
        Future<Boolean> future = executorService.submit(inputPasswordByOcr);
        Boolean aBoolean = null;
        deviceDriver.setFuture(future);
        try {
            aBoolean = future.get(waitTimeout, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            logger.warn("该线程被中断了。。。。。。");
            throw new ExecuteException("执行中断");
        } catch (ExecutionException e) {
            logger.warn("在执行的时候报错了。。。。");
            Throwable cause = e.getCause();
            if (cause instanceof ExecuteException) {
                ExecuteException ee = (ExecuteException) cause;
                throw ee;
            } else if (cause instanceof ParamMistakeException) {
                ParamMistakeException pe = (ParamMistakeException) cause;
                throw pe;
            } else if (cause instanceof NoSuchSessionException) {
                NoSuchSessionException ne = (NoSuchSessionException) cause;
                throw ne;
            } else if (cause instanceof EnvironmentException) {
                EnvironmentException ee = (EnvironmentException) cause;
                throw ee;
            }else{
                logger.error("出现了其他的问题。。。。");
                throw new ExecuteException(cause.getMessage());
            }
        } catch (TimeoutException e) {
            logger.warn("处理超时了。。。。。。");
            throw new ExecuteException("查找元素超时");
        } catch (CancellationException e) {
            logger.warn("该操作被取消了");
            throw new ExecuteException("用户取消，执行失败");
        }
        return aBoolean;
    }

    /**
     * <p>识别金额</p>
     *
     * @param deviceDriver   设备连接驱动
     * @param targets        定位控件参数
     * @param waitTimeout    超时时间
     * @param waitStatusStr  是否等待屏幕稳定
     * @param swipe          是否滑屏查找控件0-否，up-上滑，down-下滑，left-左滑,right-右滑
     * @param swipeCount     滑屏次数
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @param value          输出值
     * @return
     */
    @Keyword(alias = "识别金额", category = "0", attributes = "45")
    @Return(name = "result", comment = "输入的结果", type = DataType.OBJECT)
    public String getElementMoneyText(IExecuteContext context,
                                      @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver,
                                      @Argument(name = "targets", scope = ParamScope.STEP, comment = "控件位置", type = DataType.LIST, defaultDisplay = false) List<IStepTarget> targets,
                                      @Argument(name = "timeout", scope = ParamScope.ARGS, comment = "默认超时时间", type = DataType.INTEGER, required = false, defaultValue = "30", defaultDisplay = false) Integer waitTimeout,
                                      @Argument(name = "waitStatus", scope = ParamScope.ARGS, comment = "等待界面稳定", type = DataType.ENUM, enumValues = WhetherOrNotEnum.class, inputType = InputType.select, defaultValue = "1", defaultDisplay = false) String waitStatusStr,
                                      @Argument(name = "swipe", scope = ParamScope.ARGS, comment = "滑动方向", type = DataType.ENUM, enumValues = SwipeDirection.class, inputType = InputType.select, defaultValue = "0", required = false, defaultDisplay = false) String swipe,
                                      @Argument(name = "swipeCount", scope = ParamScope.ARGS, comment = "滑动次数", type = DataType.INTEGER, required = false, defaultValue = "0", defaultDisplay = false) Integer swipeCount,
                                      @Argument(name = "value", scope = ParamScope.OUTPUT, comment = "组件返回值", type = DataType.STRING, defaultValue = "") String value,
                                      @Argument(name = "preExecuteWait", scope = ParamScope.ARGS, comment = "执行前等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "1.0", defaultDisplay = false) Float preExecuteWait,
                                      @Argument(name = "sufExecuteWait", scope = ParamScope.ARGS, comment = "执行后等待(单位:s)", type = DataType.INTEGER, required = false, defaultValue = "1.0", defaultDisplay = false) Float sufExecuteWait) {
        GetElementMoneyTextThread getElementMoneyTextThread = new GetElementMoneyTextThread(context, deviceDriver, targets, waitTimeout, waitStatusStr, swipe, swipeCount, preExecuteWait, sufExecuteWait);
        Future<String> future = executorService.submit(getElementMoneyTextThread);
        String result = null;
        deviceDriver.setFuture(future);
        try {
            result = future.get(waitTimeout, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            logger.warn("该线程被中断了。。。。。。");
            throw new ExecuteException("执行中断");
        } catch (ExecutionException e) {
            logger.warn("在执行的时候报错了。。。。");
            Throwable cause = e.getCause();
            if (cause instanceof ExecuteException) {
                ExecuteException ee = (ExecuteException) cause;
                throw ee;
            } else if (cause instanceof ParamMistakeException) {
                ParamMistakeException pe = (ParamMistakeException) cause;
                throw pe;
            } else if (cause instanceof NoSuchSessionException) {
                NoSuchSessionException ne = (NoSuchSessionException) cause;
                throw ne;
            } else if (cause instanceof EnvironmentException) {
                EnvironmentException ee = (EnvironmentException) cause;
                throw ee;
            } else {
                logger.error("出现了其他的问题。。。。");
                throw new ExecuteException(cause.getMessage());
            }
        } catch (TimeoutException e) {
            logger.warn("处理超时了。。。。。。");
            throw new ExecuteException("查找元素超时");
        } catch (CancellationException e) {
            logger.warn("该操作被取消了");
            throw new ExecuteException("用户取消，执行失败");
        }
        setParamValue(context, value, result);
        return result;
    }

    private void setParamValue(IExecuteContext context, String variable, String value) {
        try {
            if (variable.contains("#{") && variable.contains("}")) {
                String keyValue = ReUtil.get("(?<=\\#\\{)(.+?)(?=\\})", variable, 1);
                // #{} 全局变量
                context.setProjectGlobalVariable(keyValue, value);
            }
            if (variable.contains("${") && variable.contains("}")) {
                String keyValue = ReUtil.get("(?<=\\$\\{)(.+?)(?=\\})", variable, 1);
                // #{} 全局变量
                context.setVariable(keyValue, value);
            }
        } catch (Exception e) {
            throw new ExecuteException(String.format("参数【%s】设置异常！！", variable));
        }
    }

}
