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

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import net.northking.cctp.element.core.DeviceDriver;
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.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.desktop.constants.CmdConstant;
import net.northking.cctp.element.desktop.constants.DesktopConstant;
import net.northking.cctp.element.desktop.constants.ErrorMessageConstant;
import net.northking.cctp.element.desktop.constants.RobotParamConstant;
import net.northking.cctp.element.desktop.enums.BooleanEnum;
import net.northking.cctp.element.desktop.enums.BrowserTypeEnum;
import net.northking.cctp.element.desktop.service.PublicService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>Title: ApplicationTools</p>
 * <p>Description: 应用组件</p>
 *
 * @Author chenjianfeng
 * @Version V1.0
 * @Date 2022/10/18
 * <p>Copyright: NorthKing@RPA（C）2020 版权</p>
 */
@Keywords
public class ApplicationTools {

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

    /**
     * 打开浏览器
     * @param id 步骤id
     * @param title 步骤主标题
     * @param browserType 浏览器类型
     * @param url 打开网址地址
     * @param timeout 组件超时
     * @param deviceDriver 与PC机器连接的webSocket客户端
     * @return 执行结果
     */
    @Keyword(alias = "打开浏览器", attributes = "2")
    public void openBrowser(
            @Argument(name = "id", comment = "步骤id", type = DataType.STRING, scope = ParamScope.STEP, defaultDisplay = false) String id,
            @Argument(name = "title", comment = "步骤主标题", type = DataType.STRING, required = false, notNull = false, scope = ParamScope.STEP, defaultDisplay = false) String title,
            @Argument(name = "browserType", comment = "浏览器类型", type = DataType.INTEGER, required = false, enumValues = BrowserTypeEnum.class, defaultValue = "1", inputType = InputType.select) Integer browserType,
            @Argument(name = "url", comment = "打开网址地址", type = DataType.STRING, required = false) String url,
            @Argument(name = "timeout",comment = "组件超时", type = DataType.INTEGER, required = false, notNull = false, defaultValue = "10") Integer timeout,
            @Argument(name = "__deviceDriver", comment = "与PC机器连接的webSocket客户端", type = DataType.OBJECT, scope = ParamScope.CONTEXT, defaultDisplay = false) DeviceDriver deviceDriver
    ){
        if (StrUtil.isBlank(id) || ObjectUtil.isNull(browserType) || StrUtil.isBlank(url)){
            throw new ParamMistakeException(ErrorMessageConstant.REQUEST_PARAMS_IS_BLANK);
        }
        if (deviceDriver == null){
            throw new ParamMistakeException(ErrorMessageConstant.PC_DRIVER_IS_NULL);
        }
        Map<String, Object> baseMap = new HashMap<>(16);
        baseMap.put(RobotParamConstant.CMD, CmdConstant.OPEN_BROWSER);
        baseMap.put(RobotParamConstant.SEQ_ID, id);
        baseMap.put(RobotParamConstant.TITLE, title);
        baseMap.put(RobotParamConstant.BROWSER_TYPE, browserType);
        baseMap.put(RobotParamConstant.URL, url);
        baseMap.put(RobotParamConstant.TIMEOUT, timeout);
        // 发送webSocket消息至PC执行机
        logger.info("PC Open Browser Send => " + JSONUtil.toJsonStr(baseMap));
        PublicService.commonSendAndReturn(baseMap, timeout, deviceDriver);
    }

    /**
     * 关闭浏览器
     * @param id 步骤id
     * @param title 步骤主标题
     * @param browserType 浏览器类型
     * @param deviceDriver 与PC机器连接的webSocket客户端
     * @return 执行结果
     */
    @Keyword(alias = "关闭浏览器", attributes = "2")
    public void closeBrowser(
            @Argument(name = "id", comment = "步骤id", type = DataType.STRING, scope = ParamScope.STEP, defaultDisplay = false) String id,
            @Argument(name = "title", comment = "步骤主标题", type = DataType.STRING, required = false, notNull = false, scope = ParamScope.STEP, defaultDisplay = false) String title,
            @Argument(name = "browserType", comment = "浏览器类型", type = DataType.INTEGER, required = false, enumValues = BrowserTypeEnum.class, defaultValue = "1", inputType = InputType.select) Integer browserType,
            @Argument(name = "__deviceDriver", comment = "与PC机器连接的webSocket客户端", type = DataType.OBJECT, scope = ParamScope.CONTEXT, defaultDisplay = false) DeviceDriver deviceDriver
    ){
        if (StrUtil.isBlank(id) || ObjectUtil.isNull(browserType)){
            throw new ParamMistakeException(ErrorMessageConstant.REQUEST_PARAMS_IS_BLANK);
        }
        if (deviceDriver == null){
            throw new ParamMistakeException(ErrorMessageConstant.PC_DRIVER_IS_NULL);
        }
        Map<String, Object> baseMap = new HashMap<>(8);
        baseMap.put(RobotParamConstant.CMD, CmdConstant.CLOSE_BROWSER);
        baseMap.put(RobotParamConstant.SEQ_ID, id);
        baseMap.put(RobotParamConstant.TITLE, title);
        baseMap.put(RobotParamConstant.BROWSER_TYPE, browserType);
        // 发送webSocket消息至PC执行机
        logger.info("Close Browser Send => " + JSONUtil.toJsonStr(baseMap));
        PublicService.commonSendAndReturn(baseMap, DesktopConstant.DEFAULT_TIMEOUT, deviceDriver);
    }


    /**
     * 关闭浏览器标签页
     * @param id 步骤id
     * @param title 步骤主标题
     * @param tabTitle 浏览器标签页标题
     * @param deviceDriver 与PC机器连接的webSocket客户端
     * @return 执行结果
     */
    @Keyword(alias = "关闭浏览器标签页", attributes = "2")
    public void closeBrowserTabs(
            @Argument(name = "id", comment = "步骤id", type = DataType.STRING, scope = ParamScope.STEP, defaultDisplay = false) String id,
            @Argument(name = "title", comment = "步骤主标题", type = DataType.STRING, required = false, notNull = false, scope = ParamScope.STEP, defaultDisplay = false) String title,
            @Argument(name = "tabTitle", comment = "浏览器标签页标题", type = DataType.STRING) String tabTitle,
            @Argument(name = "browserType",comment = "浏览器类型", type = DataType.INTEGER,enumValues = BrowserTypeEnum.class,defaultValue = "2",inputType = InputType.select) Integer browserType,
            @Argument(name = "__deviceDriver", comment = "与PC机器连接的webSocket客户端", type = DataType.OBJECT, scope = ParamScope.CONTEXT, defaultDisplay = false) DeviceDriver deviceDriver
    ){
        Map<String, Object> baseMap = new HashMap<>();
        baseMap.put(RobotParamConstant.CMD, CmdConstant.CLOSE_BROWSER_TABS);
        baseMap.put(RobotParamConstant.SEQ_ID, id);
        baseMap.put(RobotParamConstant.TITLE, title);
        baseMap.put(RobotParamConstant.BROWSER_TYPE, browserType);
        baseMap.put(RobotParamConstant.TAB_TITLE, tabTitle);
        // 发送webSocket消息至PC执行机
        logger.info("Close Browser Tabs Send => " + JSONUtil.toJsonStr(baseMap));
        PublicService.commonSendAndReturn(baseMap, DesktopConstant.DEFAULT_TIMEOUT, deviceDriver);
    }


    /**
     * 打开应用
     * @param id 步骤id
     * @param title 步骤主标题
     * @param targets 元素识别方法
     * @param path 应用程序exe的工作目录
     * @param parameter 应用程序传入参数
     * @param timeout 组件超时
     * @param deviceDriver 与PC机器连接的webSocket客户端
     * @return 执行结果
     */
    @Keyword(alias = "打开应用", attributes = "3")
    public void openApp(
            @Argument(name = "id", comment = "步骤id", type = DataType.STRING, scope = ParamScope.STEP, defaultDisplay = false) String id,
            @Argument(name = "title", comment = "步骤主标题", type = DataType.STRING, required = false, notNull = false, scope = ParamScope.STEP, defaultDisplay = false) String title,
            @Argument(name = "maxApp",comment = "是否应用最大化",type = DataType.BOOLEAN, enumValues = BooleanEnum.class, notNull = false, defaultValue ="true", inputType = InputType.select, defaultDisplay = false) Boolean maxApp,
            @Argument(name = "accessibility", comment = "是否开启辅助功能", type = DataType.BOOLEAN, enumValues = BooleanEnum.class, notNull = false, defaultValue ="false", inputType = InputType.select) Boolean accessibility,
            @Argument(name = "targets",comment = "元素识别方法",type = DataType.STRING,scope = ParamScope.STEP, required = false,defaultDisplay = false) List<IStepTarget> targets,
            @Argument(name = "path", comment = "应用程序exe的工作目录", type = DataType.STRING) String path,
            @Argument(name = "parameter", comment = "应用程序传入参数", type = DataType.STRING, required = false, notNull = false, defaultDisplay = false) String parameter,
            @Argument(name = "timeout",comment = "组件超时", type = DataType.INTEGER, required = false, notNull = false, defaultValue = "10") Integer timeout,
            @Argument(name = "__deviceDriver", comment = "与PC机器连接的webSocket客户端", type = DataType.OBJECT, scope = ParamScope.CONTEXT, defaultDisplay = false) DeviceDriver deviceDriver
    ){
        if (StrUtil.isBlank(id) || CollectionUtil.isEmpty(targets) || StrUtil.isBlank(path)){
            throw new ParamMistakeException(ErrorMessageConstant.REQUEST_PARAMS_IS_BLANK);
        }
        if (deviceDriver == null){
            throw new ParamMistakeException(ErrorMessageConstant.PC_DRIVER_IS_NULL);
        }
        Map<String, Object> baseMap = new HashMap<>(17);
        baseMap.put(RobotParamConstant.CMD, CmdConstant.OPEN_APP);
        baseMap.put(RobotParamConstant.SEQ_ID, id);
        baseMap.put(RobotParamConstant.TITLE, title);
        baseMap.put(RobotParamConstant.MAX_APP, maxApp);
        baseMap.put(RobotParamConstant.ACCESSIBILITY, accessibility);
        baseMap.put(RobotParamConstant.PATH, path);
        baseMap.put(RobotParamConstant.PARAMETER, parameter);
        baseMap.put(RobotParamConstant.TIMEOUT, timeout);
        PublicService.parseParamAndSend(targets, deviceDriver, CmdConstant.CMD_SUFFIX_OPEN_APP,
                baseMap, timeout, DesktopConstant.DEFAULT_TIMEUNIT);
    }

    /**
     * 关闭应用
     * @param id 步骤id
     * @param title 步骤主标题
     * @param targets 元素识别方法
     * @param deviceDriver 与PC机器连接的webSocket客户端
     * @return 执行结果
     */
    @Keyword(alias = "关闭应用", attributes = "3")
    public void closeApp(
            @Argument(name = "id", comment = "步骤id", type = DataType.STRING, scope = ParamScope.STEP, defaultDisplay = false) String id,
            @Argument(name = "title", comment = "步骤主标题", type = DataType.STRING, required = false, notNull = false, scope = ParamScope.STEP, defaultDisplay = false) String title,
            @Argument(name = "targets",comment = "元素识别方法",type = DataType.STRING,scope = ParamScope.STEP, defaultDisplay = false) List<IStepTarget> targets,
            @Argument(name = "__deviceDriver", comment = "与PC机器连接的webSocket客户端", type = DataType.OBJECT, scope = ParamScope.CONTEXT, defaultDisplay = false) DeviceDriver deviceDriver
    ){
        if (StrUtil.isBlank(id) || CollectionUtil.isEmpty(targets)){
            throw new ParamMistakeException(ErrorMessageConstant.REQUEST_PARAMS_IS_BLANK);
        }
        if (deviceDriver == null){
            throw new ParamMistakeException(ErrorMessageConstant.PC_DRIVER_IS_NULL);
        }
        Map<String, Object> baseMap = new HashMap<>(8);
        baseMap.put(RobotParamConstant.CMD, CmdConstant.CLOSE_APP);
        baseMap.put(RobotParamConstant.SEQ_ID, id);
        baseMap.put(RobotParamConstant.TITLE, title);
        PublicService.parseParamAndSend(targets, deviceDriver, CmdConstant.CMD_SUFFIX_CLOSE_APP,
                baseMap, DesktopConstant.DEFAULT_TIMEOUT, DesktopConstant.DEFAULT_TIMEUNIT);
    }
}
