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

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.ExecuteException;
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.ios.entity.ElementHandleParam;
import net.northking.cctp.element.mobile.ios.entity.PointMessage;
import net.northking.cctp.element.mobile.ios.enums.AppEnum;
import net.northking.cctp.element.mobile.ios.enums.SwipeDirection;
import net.northking.cctp.element.mobile.ios.enums.TextDirection;
import net.northking.cctp.element.mobile.ios.enums.WhetherOrNotEnum;
import net.northking.cctp.element.mobile.ios.utils.AutomationHandleUtil;
import net.northking.cctp.element.mobile.ios.utils.CommonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.concurrent.CancellationException;

import static net.northking.cctp.element.mobile.ios.utils.AutomationHandleUtil.getRedDotScreenShotWithPoint;

/**
 * ios新版的组件
 */
@Keywords
public class IOSNewTools {

    private Logger logger = LoggerFactory.getLogger(IOSNewTools.class);

    /**
     * <p>点击控件（ios新）</p>
     *
     * @param deviceDriver   设备驱动链接
     * @param targets        定位控件的信息
     * @param waitTimeout    默认超时时间
     * @param waitStatusStr  是否等待界面稳定
     * @param swipe          滑动方向
     * @param swipeCount     滑动次数
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    @Keyword(alias = "点击控件(ios新)", category = "0", attributes = "5", 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
    ) {
        boolean success = false;
        try {
            CommonUtils.handlePreExecuteWait(preExecuteWait);  //执行前等待
            boolean waitStatus = "1".equals(waitStatusStr);   //是否等待界面稳定
            ElementHandleParam param = ElementHandleParam.builder(deviceDriver)
                    .useContext(context)
                    .withTargets(targets)
                    .waitTimeout(waitTimeout)
                    .searchSwipeDirection(swipe)
                    .withSwipeCount(swipeCount)
                    .waitStatus(waitStatus);
            success = AutomationHandleUtil.clickElement(param);
            CommonUtils.handleSufExecuteWait(sufExecuteWait);  //执行后等待
        } catch (InterruptedException ie) {
            logger.warn("用户取消查询元素");
            throw new ExecuteException("取消操作");
        } catch (Exception e) {
            logger.error("出现了其他的问题。。。。", e);
            throw new ExecuteException(e.getMessage());
        }
        return success;
    }

    /**
     * <p>判断是否界面上存在某一个元素（ios新）</p>
     *
     * @param deviceDriver   设备驱动
     * @param targets        元素的信息
     * @param waitTimeout    默认超时时间
     * @param waitStatusStr  是否等待界面稳定
     * @param diffussion     OCR识别方式时是否需要模糊匹配
     * @param swipe          滑动方向
     * @param swipeCount     滑动次数
     * @param value          返回结果接受的值
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    @Keyword(alias = "是否存在元素（ios新）", category = "0", attributes = "5")
    @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 = "diffussion", scope = ParamScope.ARGS, comment = "OCR识别方式时是否需要模糊匹配", type = DataType.ENUM, enumValues = WhetherOrNotEnum.class, inputType = InputType.select, defaultValue = "0", notNull = false, required = false, defaultDisplay = false) String diffussion,
                             @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) {
        Boolean success = false;
        try {
            CommonUtils.handlePreExecuteWait(preExecuteWait);  //执行前等待
            boolean waitStatus = "1".equals(waitStatusStr);   //是否等待界面稳定
            ElementHandleParam param = ElementHandleParam.builder(deviceDriver)
                    .useContext(context)
                    .withTargets(targets)
                    .waitTimeout(waitTimeout)
                    .searchSwipeDirection(swipe)
                    .withSwipeCount(swipeCount)
                    .withDiffussion(diffussion)
                    .waitStatus(waitStatus);
            success = AutomationHandleUtil.ifElement(param);
            CommonUtils.handleSufExecuteWait(sufExecuteWait);  //执行后等待
        } catch (InterruptedException ie) {
            logger.warn("用户取消查询元素");
            throw new ExecuteException("取消操作");
        } catch (Exception e) {
            logger.error("出现了其他的问题。。。。", e);
            success = false;
        }
        CommonUtils.setParamValue(context, value, success.toString());
        return success;
    }

    /**
     * <p>标准滑动屏幕(ios)</p>
     *
     * @param direction      滑动方向
     * @param deviceDriver   设备连接
     * @param size           滑动距离
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    @Keyword(alias = "标准滑动（ios新）", category = "0", attributes = "5", 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 = "timeout", scope = ParamScope.ARGS, comment = "默认超时时间", type = DataType.INTEGER, required = false, defaultValue = "30", defaultDisplay = false) Integer waitTimeout,
            @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
    ) {
        Boolean success = false;
        try {
            CommonUtils.handlePreExecuteWait(preExecuteWait);  //执行前等待
            ElementHandleParam param = ElementHandleParam.builder(deviceDriver)
                    .waitTimeout(waitTimeout)
                    .swipeDirection(direction)
                    .withSwipeSize(size);
            success = AutomationHandleUtil.standardSwipe(param);
            CommonUtils.handleSufExecuteWait(sufExecuteWait);  //执行后等待
        } catch (InterruptedException ie) {
            logger.warn("用户取消查询元素");
            throw new ExecuteException("取消操作");
        } catch (Exception e) {
            logger.error("出现了其他的问题。。。。", e);
            throw new ExecuteException(e.getMessage());
        }
        return success;
    }

    /**
     * <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 = "控件滑动（ios新）", category = "0", attributes = "5", 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, 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) {
        Boolean success = false;
        try {
            CommonUtils.handlePreExecuteWait(preExecuteWait);  //执行前等待
            boolean waitStatus = "1".equals(waitStatusStr);   //是否等待界面稳定
            ElementHandleParam param = ElementHandleParam.builder(deviceDriver)
                    .useContext(context)
                    .withTargets(targets)
                    .waitTimeout(waitTimeout)
                    .searchSwipeDirection(swipe)
                    .withSwipeCount(swipeCount)
                    .swipeDirection(direction)
                    .withSwipeSize(size)
                    .waitStatus(waitStatus);
            success = AutomationHandleUtil.elementSwipe(param);
            CommonUtils.handleSufExecuteWait(sufExecuteWait);  //执行后等待
        } catch (InterruptedException ie) {
            logger.warn("用户取消查询元素");
            throw new ExecuteException("取消操作");
        } catch (Exception e) {
            logger.error("出现了其他的问题。。。。", e);
            throw new ExecuteException(e.getMessage());
        }
        return success;
    }

    /**
     * <p>在控件中输入文本（ios新）</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 xMove          水平偏移量
     * @param yMove          垂直偏移量
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    @Keyword(alias = "控件输入文本（ios新）", category = "0", attributes = "5", 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 = "xMove", scope = ParamScope.ARGS, comment = "水平偏移量", type = DataType.STRING, required = false, defaultValue = "0", defaultDisplay = false, notNull = false) String xMove,
                             @Argument(name = "yMove", scope = ParamScope.ARGS, comment = "垂直偏移量", type = DataType.STRING, required = false, defaultValue = "0", defaultDisplay = false, notNull = false) String 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
    ) {
        Boolean success = false;
        try {
            CommonUtils.handlePreExecuteWait(preExecuteWait);  //执行前等待
            boolean waitStatus = "1".equals(waitStatusStr);   //是否等待界面稳定
            boolean clear = "1".equals(cleanStr);   //是否清除文本框
            // 设置偏移量
            Integer xMoveInt = StringUtils.isEmpty(xMove) ? 0 : Integer.parseInt(xMove);
            Integer yMoveInt = StringUtils.isEmpty(yMove) ? 0 : Integer.parseInt(yMove);
            ElementHandleParam param = ElementHandleParam.builder(deviceDriver)
                    .useContext(context)
                    .withTargets(targets)
                    .waitTimeout(waitTimeout)
                    .searchSwipeDirection(swipe)
                    .withSwipeCount(swipeCount)
                    .clear(clear)
                    .withInputTextValue(text)
                    .waitStatus(waitStatus)
                    .withXMove(xMoveInt)
                    .withYMove(yMoveInt);
            success = AutomationHandleUtil.elementInput(param);
            CommonUtils.handleSufExecuteWait(sufExecuteWait);  //执行后等待
        } catch (InterruptedException ie) {
            logger.warn("用户取消查询元素");
            throw new ExecuteException("取消操作");
        } catch (Exception e) {
            logger.error("出现了其他的问题。。。。", e);
            throw new ExecuteException(e.getMessage());
        }
        return success;
    }

    /**
     * <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 = "获取控件的值（ios新）", category = "0", attributes = "5")
    @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) {
        String result = "";
        try {
            CommonUtils.handlePreExecuteWait(preExecuteWait);  //执行前等待
            boolean waitStatus = "1".equals(waitStatusStr);   //是否等待界面稳定
            ElementHandleParam param = ElementHandleParam.builder(deviceDriver)
                    .useContext(context)
                    .withTargets(targets)
                    .waitTimeout(waitTimeout)
                    .searchSwipeDirection(swipe)
                    .withSwipeCount(swipeCount)
                    .waitStatus(waitStatus);
            result = AutomationHandleUtil.getElementValue(param);
            CommonUtils.handleSufExecuteWait(sufExecuteWait);  //执行后等待
            CommonUtils.setParamValue(context, value, result);
        } catch (InterruptedException ie) {
            logger.warn("用户取消查询元素");
            throw new ExecuteException("取消操作");
        } catch (Exception e) {
            logger.error("出现了其他的问题。。。。", e);
            throw new ExecuteException(e.getMessage());
        }
        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 = "长按控件(ios新)", category = "0", attributes = "5", 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 = "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
    ) {
        boolean success = false;
        try {
            CommonUtils.handlePreExecuteWait(preExecuteWait);  //执行前等待
            boolean waitStatus = "1".equals(waitStatusStr);   //是否等待界面稳定
            ElementHandleParam param = ElementHandleParam.builder(deviceDriver)
                    .useContext(context)
                    .withTargets(targets)
                    .waitTimeout(waitTimeout)
                    .searchSwipeDirection(swipe)
                    .withSwipeCount(swipeCount)
                    .waitStatus(waitStatus)
                    .withXMove(xMove)
                    .withYMove(yMove);
            success = AutomationHandleUtil.longPressElement(param);
            CommonUtils.handleSufExecuteWait(sufExecuteWait);  //执行后等待
        } catch (InterruptedException ie) {
            logger.warn("用户取消查询元素");
            throw new ExecuteException("取消操作");
        } catch (Exception e) {
            logger.error("出现了其他的问题。。。。", e);
            throw new ExecuteException(e.getMessage());
        }
        return success;
    }

    /**
     * <p>断言元素</p>
     *
     * @param deviceDriver   设备连接驱动
     * @param targets        定位控件参数
     * @param waitTimeout    超时时间
     * @param waitStatusStr  是否等待屏幕稳定
     * @param diffussion     OCR识别方式时是否需要模糊匹配
     * @param swipe          是否滑屏查找控件0-否，up-上滑，down-下滑，left-左滑,right-右滑
     * @param swipeCount     滑屏次数
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    @Keyword(alias = "断言元素（ios新）", category = "0", attributes = "5", 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 = "diffussion", scope = ParamScope.ARGS, comment = "OCR识别方式时是否需要模糊匹配", type = DataType.ENUM, enumValues = WhetherOrNotEnum.class, inputType = InputType.select, defaultValue = "0", notNull = false, required = false, defaultDisplay = false) String diffussion,
                                 @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
    ) {
        Boolean success = false;
        try {
            CommonUtils.handlePreExecuteWait(preExecuteWait);  //执行前等待
            boolean waitStatus = "1".equals(waitStatusStr);   //是否等待界面稳定
            ElementHandleParam param = ElementHandleParam.builder(deviceDriver)
                    .useContext(context)
                    .withTargets(targets)
                    .waitTimeout(waitTimeout)
                    .searchSwipeDirection(swipe)
                    .withSwipeCount(swipeCount)
                    .withDiffussion(diffussion)
                    .waitStatus(waitStatus);
            success = AutomationHandleUtil.ifElement(param);
            CommonUtils.handleSufExecuteWait(sufExecuteWait);  //执行后等待
        } catch (InterruptedException ie) {
            logger.warn("用户取消查询元素");
            throw new ExecuteException("取消操作");
        } catch (Exception e) {
            logger.error("出现了其他的问题。。。。", e);
            throw new ExecuteException(e.getMessage());
        }
        if (success != null && success) {
            return success;
        }
        throw new AssertException("断言失败，找不到目标元素");
    }

    /**
     * <p>验证码识别</p>
     *
     * @param deviceDriver   设备连接驱动
     * @param targets        定位元素参数
     * @param waitTimeout    等待超时时间
     * @param value          赋值变量
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    @Keyword(alias = "识别验证码（ios新）", category = "0", attributes = "5")
    @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 = "codeType", scope = ParamScope.ARGS, comment = "验证码类型", type = DataType.INTEGER, required = false, defaultValue = "1", defaultDisplay = false) Integer codeType,
            @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

    ) {
        String result = "";
        try {
            CommonUtils.handlePreExecuteWait(preExecuteWait);  //执行前等待
            boolean waitStatus = "1".equals(waitStatusStr);   //是否等待界面稳定
            ElementHandleParam param = ElementHandleParam.builder(deviceDriver)
                    .useContext(context)
                    .withTargets(targets)
                    .waitTimeout(waitTimeout)
                    .codeType(codeType)
                    .searchSwipeDirection("0")     //不滑动
                    .withSwipeCount(1)
                    .waitStatus(waitStatus);
            result = AutomationHandleUtil.getVerificationCode(param);
            CommonUtils.handleSufExecuteWait(sufExecuteWait);  //执行后等待
            CommonUtils.setParamValue(context, value, result);
        } catch (InterruptedException ie) {
            logger.warn("用户取消查询元素");
            throw new ExecuteException("取消操作");
        } catch (Exception e) {
            logger.error("出现了其他的问题。。。。", e);
            throw new ExecuteException(e.getMessage());
        }
        return result;
    }

    /**
     * <p>点击文本</p>
     *
     * @param deviceDriver   设备连接驱动
     * @param waitTimeout    默认超时时间
     * @param text           点击的文本
     * @param index          选择第几个
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    @Keyword(alias = "点击文本(ios新)", category = "0", attributes = "5", 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

    ) {
        boolean success = false;
        try {
            CommonUtils.handlePreExecuteWait(preExecuteWait);  //执行前等待
            ElementHandleParam param = ElementHandleParam.builder(deviceDriver)
                    .useContext(context)
                    .waitTimeout(waitTimeout)
                    .searchSwipeDirection("0")   //不滑动
                    .withSwipeCount(1)
                    .withText(text)
                    .withIndex(index);
            success = AutomationHandleUtil.clickText(param);
            CommonUtils.handleSufExecuteWait(sufExecuteWait);  //执行后等待
        } catch (InterruptedException ie) {
            logger.warn("用户取消查询元素");
            throw new ExecuteException("取消操作");
        } catch (Exception e) {
            logger.error("出现了其他的问题。。。。", e);
            throw new ExecuteException(e.getMessage());
        }
        return success;
    }

    /**
     * <p>点击文本(新)</p>
     *
     * @param deviceDriver   设备连接驱动
     * @param waitTimeout    默认超时时间
     * @param text           点击的文本
     * @param index          选择第几个
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    @Keyword(alias = "点击文本(新)(ios新)", category = "0", attributes = "5", 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

    ) {
        boolean success = false;
        try {
            CommonUtils.handlePreExecuteWait(preExecuteWait);  //执行前等待
            ElementHandleParam param = ElementHandleParam.builder(deviceDriver)
                    .useContext(context)
                    .waitTimeout(waitTimeout)
                    .searchSwipeDirection("0")   //不滑动
                    .withSwipeCount(1)
                    .withText(text)
                    .withIndex(index);
            success = AutomationHandleUtil.clickTextNew(param);
            CommonUtils.handleSufExecuteWait(sufExecuteWait);  //执行后等待
        } catch (InterruptedException ie) {
            logger.warn("用户取消查询元素");
            throw new ExecuteException("取消操作");
        } catch (Exception e) {
            logger.error("出现了其他的问题。。。。", e);
            throw new ExecuteException(e.getMessage());
        }
        return success;
    }

    /**
     * <p>判断当前页面是否存在文本</p>
     *
     * @param deviceDriver   设备连接驱动
     * @param waitTimeout    默认等待时长
     * @param text           判断的文本
     * @param value          接受返回结果
     * @param diffussion     是否需要模糊匹配
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return 返回判断的结果
     */
    @Keyword(alias = "是否存在文本(ios新)", category = "0", attributes = "5")
    @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 = "diffussion", scope = ParamScope.ARGS, comment = "是否需要模糊匹配", type = DataType.ENUM, enumValues = WhetherOrNotEnum.class, inputType = InputType.select, defaultValue = "0", notNull = false, required = false, defaultDisplay = false) String diffussion,
            @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
    ) {
        boolean success = false;
        try {
            CommonUtils.handlePreExecuteWait(preExecuteWait);  //执行前等待
            ElementHandleParam param = ElementHandleParam.builder(deviceDriver)
                    .useContext(context)
                    .waitTimeout(waitTimeout)
                    .searchSwipeDirection(swipe)
                    .withSwipeCount(swipeCount)
                    .withDiffussion(diffussion)
                    .withText(text);
            PointMessage point = AutomationHandleUtil.ifText(param);
            success = point != null;
            if (success) {
                getRedDotScreenShotWithPoint(param, point);
            }
            CommonUtils.handleSufExecuteWait(sufExecuteWait);  //执行后等待
        } catch (InterruptedException ie) {
            logger.warn("用户取消查询元素");
            throw new ExecuteException("取消操作");
        } catch (Exception e) {
            logger.error("出现了其他的问题。。。。", e);
            success = false;
        }
        CommonUtils.setParamValue(context, value, String.valueOf(success));
        return success;
    }

    /**
     * <p>app处理</p>
     *
     * @param deviceDriver   设备连接驱动
     * @param appPackage     启动包名
     * @param waitTimeout    等待超时时间
     * @param type           操作应用的类型0-关闭，1-启动
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    @Keyword(alias = "app处理(ios新)", category = "0", attributes = "5", 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) {
        boolean success = false;
        try {
            CommonUtils.handlePreExecuteWait(preExecuteWait);  //执行前等待
            ElementHandleParam param = ElementHandleParam.builder(deviceDriver)
                    .withAppPackage(appPackage)
                    .withType(type)
                    .useContext(context)
                    .waitTimeout(waitTimeout);
            success = AutomationHandleUtil.handleApp(param);
            CommonUtils.handleSufExecuteWait(sufExecuteWait);  //执行后等待
        } catch (InterruptedException ie) {
            logger.warn("用户取消查询元素");
            throw new ExecuteException("取消操作");
        } catch (Exception e) {
            logger.error("出现了其他的问题。。。。", e);
            throw new ExecuteException(e.getMessage());
        }
        return success;
    }

    /**
     * <p>点击home键</p>
     *
     * @param deviceDriver   设备连接驱动
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    @Keyword(alias = "点击home键(ios新)", category = "0", attributes = "5", 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) {
        boolean success = false;
        try {
            CommonUtils.handlePreExecuteWait(preExecuteWait);  //执行前等待
            ElementHandleParam param = ElementHandleParam.builder(deviceDriver)
                    .useContext(context)
                    .waitTimeout(30);
            success = AutomationHandleUtil.pressKeyHome(param);
            CommonUtils.handleSufExecuteWait(sufExecuteWait);  //执行后等待
        } catch (InterruptedException ie) {
            logger.warn("用户取消查询元素");
            throw new ExecuteException("取消操作");
        } catch (Exception e) {
            logger.error("出现了其他的问题。。。。", e);
            throw new ExecuteException(e.getMessage());
        }
        return success;
    }

    /**
     * <p>等待</p>
     *
     * @param waitTime 等待时间（单位s）
     * @return
     */
    @Keyword(alias = "等待(ios新)", category = "0", attributes = "5")
    @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
    ) {
        try {
            long time = waitTime * 1000L;
            Thread.sleep(time);
        } catch (InterruptedException e) {
//            Thread.currentThread().interrupt();
            logger.error("等待失败", e);
            throw new ExecuteException("取消操作");
        } catch (CancellationException e) {
            logger.warn("该操作被取消了");
            throw new ExecuteException("取消操作");
        }
        return true;
    }

//    /**
//     * <p>接口方式获取验证码（临时）</p>
//     *
//     * @return
//     */
//    @Keyword(alias = "接口方式获取验证码(ios新)", category = "0", attributes = "5")
//    @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);
//        }
//        CommonUtils.setParamValue(context,value,result);
//        return result;
//    }

    /**
     * <p>密码输入(ocr)</p>
     *
     * @param deviceDriver   设备驱动链接
     * @param targets        定位控件的信息
     * @param waitTimeout    默认超时时间
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    @Keyword(alias = "密码输入(ocr)(ios新)", category = "0", attributes = "5", 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 = "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
    ) {
        boolean success = false;
        try {
            CommonUtils.handlePreExecuteWait(preExecuteWait);  //执行前等待
            ElementHandleParam param = ElementHandleParam.builder(deviceDriver)
                    .useContext(context)
                    .withTargets(targets)
                    .waitTimeout(waitTimeout)
                    .searchSwipeDirection("0")     //不滑动
                    .withSwipeCount(1)
                    .withText(text);
            success = AutomationHandleUtil.inputPasswordByOcr(param);
            CommonUtils.handleSufExecuteWait(sufExecuteWait);  //执行后等待
        } catch (InterruptedException ie) {
            logger.warn("用户取消查询元素");
            throw new ExecuteException("取消操作");
        } catch (Exception e) {
            logger.error("出现了其他的问题。。。。", e);
            throw new ExecuteException(e.getMessage());
        }
        return success;
    }

    /**
     * <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 = "识别金额(ios新)", category = "0", attributes = "5")
    @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 = "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) {
        String result = "";
        try {
            CommonUtils.handlePreExecuteWait(preExecuteWait);  //执行前等待
            boolean waitStatus = "1".equals(waitStatusStr);   //是否等待界面稳定
            ElementHandleParam param = ElementHandleParam.builder(deviceDriver)
                    .useContext(context)
                    .withTargets(targets)
                    .waitTimeout(waitTimeout)
                    .searchSwipeDirection("0")     //不滑动
                    .withSwipeCount(1)
                    .waitStatus(waitStatus);
            result = AutomationHandleUtil.getElementMoneyText(param);
            if (result != null) {
                result = result.replace("，", ",");
                result = result.replace("。", ".");
                result = result.replace(" ", "");
            }
            CommonUtils.handleSufExecuteWait(sufExecuteWait);  //执行后等待
        } catch (InterruptedException ie) {
            logger.warn("用户取消查询元素");
            throw new ExecuteException("取消操作");
        } catch (Exception e) {
            logger.error("出现了其他的问题。。。。", e);
        }
        CommonUtils.setParamValue(context, value, result);
        return result;
    }

    /**
     * <p>屏幕截图（ios新）</p>
     *
     * @param deviceDriver   设备连接驱动
     * @param waitTimeout    默认超时时间
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    @Keyword(alias = "屏幕截图（ios新）", category = "0", attributes = "5")
    @Return(name = "result", comment = "是否截图成功", type = DataType.BOOLEAN)
    public Boolean screenShot(
            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 = "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

    ) {
        Boolean result = false;
        try {
            CommonUtils.handlePreExecuteWait(preExecuteWait);  //执行前等待
            ElementHandleParam param = ElementHandleParam.builder(deviceDriver)
                    .useContext(context)
                    .waitTimeout(waitTimeout);
            result = AutomationHandleUtil.screenShot(param);
            CommonUtils.handleSufExecuteWait(sufExecuteWait);  //执行后等待
        } catch (InterruptedException ie) {
            logger.warn("用户取消查询元素");
            throw new ExecuteException("取消操作");
        } catch (Exception e) {
            logger.error("出现了其他的问题。。。。", e);
            throw new ExecuteException(e.getMessage());
        }
        return result;
    }

    /**
     * <p>获取控件的值（ios新）（OCR方式）</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 = "获取控件的值（ios新）（OCR方式）", category = "0", attributes = "5")
    @Return(name = "result", comment = "输入的结果", type = DataType.OBJECT)
    public String getElementValueByOcr(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 = "ifMoney", scope = ParamScope.ARGS, comment = "是否识别金额", type = DataType.ENUM, enumValues = WhetherOrNotEnum.class, inputType = InputType.select, defaultValue = "1", defaultDisplay = false) String ifMoney,
                                       @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) {
        String result = "";
        try {
            CommonUtils.handlePreExecuteWait(preExecuteWait);  //执行前等待
            boolean waitStatus = "1".equals(waitStatusStr);   //是否等待界面稳定
            ElementHandleParam param = ElementHandleParam.builder(deviceDriver)
                    .useContext(context)
                    .withTargets(targets)
                    .waitTimeout(waitTimeout)
                    .searchSwipeDirection("0")     //不滑动
                    .withSwipeCount(1)
                    .waitStatus(waitStatus)
                    .withIfMoney(ifMoney);
            result = AutomationHandleUtil.getElementValueByOcr(param);
            CommonUtils.handleSufExecuteWait(sufExecuteWait);  //执行后等待
            CommonUtils.setParamValue(context, value, result);
        } catch (InterruptedException ie) {
            logger.warn("用户取消查询元素");
            throw new ExecuteException("取消操作");
        } catch (Exception e) {
            logger.error("出现了其他的问题。。。。", e);
            throw new ExecuteException(e.getMessage());
        }
        return result;
    }


    /**
     * 滑动查找控件（ios新）
     * @param context 上下文
     * @param direction 控件滑动方向
     * @param deviceDriver 设备连接
     * @param targets 目标元素
     * @param referencesStr 滑动元素
     * @param waitTimeout 默认超时时间
     * @param index 多个时定位第几个
     * @param swipeSizePer 每次滑动的距离，屏幕的百分比（输入0-1之间的小数），无特殊需求建议给值<0.5，给值过大会导致组件执行成功但是目标元素滑出屏幕
     * @param waitStatusStr 等待界面稳定
     * @param value 组件返回值
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    @Keyword(alias = "滑动查找控件（ios新）", category = "0", attributes = "5")
    @Return(name = "result", comment = "滑动的结果", type = DataType.OBJECT)
    public boolean swipeAndFindTargetElement(IExecuteContext context,
                                            @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 = "targets", scope = ParamScope.STEP, comment = "目标元素", type = DataType.LIST, defaultDisplay = false,inputType = InputType.element) List<IStepTarget> targets,
                                            @Argument(name = "references", scope = ParamScope.ARGS, comment = "滑动元素", type = DataType.LIST, defaultDisplay = false, required = false,inputType = InputType.element) String referencesStr,
                                            @Argument(name = "timeout", scope = ParamScope.ARGS, comment = "默认超时时间", type = DataType.INTEGER, required = false, defaultValue = "30", defaultDisplay = false) Integer waitTimeout,
                                            @Argument(name = "index", scope = ParamScope.ARGS, comment = "多个时定位第几个", type = DataType.INTEGER, defaultValue = "1",defaultDisplay = false) Integer index,
                                            @Argument(name = "swipeSizePer", scope = ParamScope.ARGS, comment = "每次滑动的距离", type = DataType.STRING, defaultValue = "0.5", defaultDisplay = false, notNull = false, required = false) String swipeSizePer,
                                            @Argument(name = "waitStatus", scope = ParamScope.ARGS, comment = "等待界面稳定", type = DataType.ENUM, enumValues = WhetherOrNotEnum.class, inputType = InputType.select, defaultValue = "1", defaultDisplay = false) String waitStatusStr,
                                            @Argument(name = "value", scope = ParamScope.OUTPUT, comment = "组件返回值",required = false, 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) {
        logger.debug("拿到的reference为：{}",referencesStr);
        Boolean result = null;
        try {
            CommonUtils.handlePreExecuteWait(preExecuteWait);  //执行前等待
            boolean waitStatus = "1".equals(waitStatusStr);   //是否等待界面稳定
            ElementHandleParam param = ElementHandleParam.builder(deviceDriver)
                    .useContext(context)
                    .withTargets(targets)
                    .waitTimeout(waitTimeout)
                    .searchSwipeDirection("0")     //不滑动
                    .withSwipeCount(1)
                    .waitStatus(waitStatus)
                    .swipeDirection(direction)
                    .withIndex(index)
                    .withReferences(referencesStr)
                    .withSwipeSizePer(swipeSizePer);
            result = AutomationHandleUtil.swipeAndFindTargetElement(param);
            CommonUtils.handleSufExecuteWait(sufExecuteWait);  //执行后等待
            if (result != null && !StringUtils.isEmpty(value)) {
                CommonUtils.setParamValue(context,value,result.toString());
            }
        } catch (InterruptedException ie) {
            logger.warn("用户取消查询元素");
            throw new ExecuteException("取消操作");
        } catch (Exception e) {
            logger.error("出现了其他的问题。。。。", e);
            throw new ExecuteException(e.getMessage());
        }
        return result;
    }

    /**
     * <p>获取指定文字指定方向的数值内容</p>
     *
     * @param direction      滑动方向
     * @param deviceDriver   设备驱动
     * @param waitTimeout    默认超时时间
     * @param text           指定文本
     * @param direction      指定方向
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    @Keyword(alias = "获取指定文字指定方向的内容", category = "0", attributes = "5")
    @Return(name = "result", comment = "返回的结果", type = DataType.BOOLEAN)
    public String getTextDirectionText(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 = "index", scope = ParamScope.ARGS, comment = "第几个", type = DataType.INTEGER, defaultValue = "1") Integer index,
                                       @Argument(name = "text", comment = "指定文本", scope = ParamScope.ARGS, type = DataType.STRING) String text,
                                       @Argument(name = "direction", scope = ParamScope.ARGS, comment = "指定方向", type = DataType.ENUM, enumValues = TextDirection.class, inputType = InputType.select, defaultValue = "右") String direction,
                                       @Argument(name = "ifMoney", scope = ParamScope.ARGS, comment = "是否识别金额", type = DataType.ENUM, enumValues = WhetherOrNotEnum.class, inputType = InputType.select, defaultValue = "0", notNull = false, required = false , defaultDisplay = false) String ifMoney,
                                       @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) {
        String result = "";
        try {
            CommonUtils.handlePreExecuteWait(preExecuteWait);  //执行前等待
            ElementHandleParam param = ElementHandleParam.builder(deviceDriver)
                    .useContext(context)
                    .withText(text)
                    .withIndex(index)
                    .waitTimeout(waitTimeout)
                    .withIfMoney(ifMoney)
                    .withDirection(direction);
            result = AutomationHandleUtil.getTextDirectionText(param);
            if (org.apache.commons.lang3.StringUtils.isNotEmpty(result) && "1".equals(ifMoney)) {
                result = result.replace("，", ",");
                result = result.replace("。", ".");
                result = result.replace(" ", "");
            }
            CommonUtils.handleSufExecuteWait(sufExecuteWait);  //执行后等待
            CommonUtils.setParamValue(context, value, result);
        } catch (InterruptedException ie) {
            logger.warn("用户取消查询元素");
            throw new ExecuteException("取消操作");
        } catch (Exception e) {
            logger.error("出现了其他的问题。。。。", e);
            throw new ExecuteException(e.getMessage());
        }
        return result;
    }

    /**
     * <p>滑动解锁（ios新）</p>
     *
     * @param context 上下文
     * @param deviceDriver 设备连接
     * @param firstPointStr 左上角点
     * @param secondPointStr 左上角右边的点
     * @param thirdPointStr 左上角下面的点
     * @param pointNum 每一行、列的点数
     * @param passingPoints 经过的点 从上至下，从左至右，9个点依次对应数字1至9，填写格式为：[1,2,3,4,5,6]
     * @param waitTime 等待时间
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    @Keyword(alias = "滑动解锁（ios新）", category = "0", attributes = "5", commonlyUse = true)
    @Return(name = "result", comment = "是否滑动成功", type = DataType.BOOLEAN)
    public Boolean pressAndSwipe(
            IExecuteContext context,
            @Argument(name = "__deviceDriver", scope = ParamScope.CONTEXT, comment = "设备连接", type = DataType.OBJECT) DeviceDriver deviceDriver,
            @Argument(name = "firstPoint", scope = ParamScope.ARGS, comment = "左上角点", type = DataType.LIST, defaultDisplay = true,inputType = InputType.element) String firstPointStr,
            @Argument(name = "secondPoint", scope = ParamScope.ARGS, comment = "左上角右边的点", type = DataType.LIST, defaultDisplay = true,inputType = InputType.element) String secondPointStr,
            @Argument(name = "thirdPoint", scope = ParamScope.ARGS, comment = "左上角下面的点", type = DataType.LIST, defaultDisplay = true,inputType = InputType.element) String thirdPointStr,
            @Argument(name = "pointNum", scope = ParamScope.ARGS, comment = "每一行、列的点数", type = DataType.INTEGER, defaultDisplay = false,defaultValue = "3") Integer pointNum,
            @Argument(name = "passingPoints", scope = ParamScope.ARGS, comment = "经过的点", type = DataType.LIST, defaultDisplay = true) List<Integer> passingPoints,
            @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

    ) {
        Boolean result = false;
        try {
            CommonUtils.handlePreExecuteWait(preExecuteWait);  //执行前等待
            ElementHandleParam param = ElementHandleParam.builder(deviceDriver)
                    .useContext(context)
                    .waitTimeout(waitTime)
                    .withPassingPoints(passingPoints)
					.withPointData(firstPointStr, secondPointStr, thirdPointStr)
                     .withPointNum(pointNum);
            result = AutomationHandleUtil.pressAndSwipe(param);
            CommonUtils.handleSufExecuteWait(sufExecuteWait);  //执行后等待
        } catch (InterruptedException ie) {
            logger.warn("用户取消查询元素");
            throw new ExecuteException("取消操作");
        } catch (Exception e) {
            logger.error("出现了其他的问题。。。。", e);
            throw new ExecuteException(e.getMessage());
        }
        return result;
    }

    /**
     * <p>if存在控件执行点击（ios新）</p>
     *
     * @param deviceDriver   设备驱动链接
     * @param targets        定位控件的信息
     * @param waitTimeout    默认超时时间
     * @param waitStatusStr  是否等待界面稳定
     * @param swipe          滑动方向
     * @param swipeCount     滑动次数
     * @param preExecuteWait 执行前等待
     * @param sufExecuteWait 执行后等待
     * @return
     */
    @Keyword(alias = "if存在控件执行点击(ios新)", category = "0", attributes = "5", commonlyUse = true)
    @Return(name = "result", comment = "点击结果", type = DataType.BOOLEAN)
    public boolean clickIfExistElement(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,
                                       @Argument(name = "value", scope = ParamScope.OUTPUT, comment = "组件返回值", type = DataType.STRING, defaultValue = "", required = false) String value
    ) {
        Boolean success = false;
        try {
            CommonUtils.handlePreExecuteWait(preExecuteWait);  //执行前等待
            boolean waitStatus = "1".equals(waitStatusStr);   //是否等待界面稳定
            ElementHandleParam param = ElementHandleParam.builder(deviceDriver)
                    .useContext(context)
                    .withTargets(targets)
                    .waitTimeout(waitTimeout)
                    .searchSwipeDirection(swipe)
                    .withSwipeCount(swipeCount)
                    .waitStatus(waitStatus);
            success = AutomationHandleUtil.clickElement(param);
            CommonUtils.handleSufExecuteWait(sufExecuteWait);  //执行后等待
        } catch (InterruptedException ie) {
            logger.warn("用户取消查询元素");
            throw new ExecuteException("取消操作");
        } catch (Exception e) {
            logger.error("出现了其他的问题。。。。", e);
        }
        if (success != null && !StringUtils.isEmpty(value)) {
            CommonUtils.setParamValue(context,value,success.toString());
        }
        return success;
    }
}
