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

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.ios.IOSDriver;
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.exception.ExecuteException;
import net.northking.cctp.element.core.exception.ParamMistakeException;
import net.northking.cctp.element.mobile.constants.ConfigPath;
import net.northking.cctp.element.mobile.constants.UsingType;
import net.northking.cctp.element.mobile.entity.PointMessage;
import net.northking.cctp.element.mobile.utils.CommonUtils;
import net.northking.cctp.element.mobile.utils.HttpUtils;
import net.northking.cctp.element.mobile.utils.phoneUtils.ElementUtil;
import net.northking.cctp.element.mobile.utils.phoneUtils.ScreenUtil;
import org.openqa.selenium.*;
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.CollectionUtils;

import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

public class GetElementValueByOcrThread implements Callable<String> {

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

    private IExecuteContext context;
    private DeviceDriver deviceDriver;
    private List<IStepTarget> targets;
    private Integer waitTimeout;
    private Float preExecuteWait;
    private Float sufExecuteWait;


    public GetElementValueByOcrThread(IExecuteContext context, DeviceDriver deviceDriver, List<IStepTarget> targets, Integer waitTimeout, Float preExecuteWait, Float sufExecuteWait) {
        this.context = context;
        this.deviceDriver = deviceDriver;
        this.targets = targets;
        this.waitTimeout = waitTimeout;
        this.preExecuteWait = preExecuteWait;
        this.sufExecuteWait = sufExecuteWait;

    }

    @Override
    public String call() throws Exception {
        CommonUtils.handlePreExecuteWait(preExecuteWait);
        if (null == waitTimeout || waitTimeout <= 0) {
            waitTimeout = 30;
        }
        String result = "";
        AppiumDriver<WebElement> driver = (AppiumDriver<WebElement>) deviceDriver;
        WebElement webElement = null;
        for (IStepTarget target : targets) {
            webElement = xpathFind(driver, target);
            if (webElement != null) {
                result = getElementValueByOcr(context, driver, webElement);
                break;
            }
        }
        CommonUtils.handleSufExecuteWait(sufExecuteWait);
        return result;
    }

    /**
     * xpath找元素
     *
     * @param driver
     * @param target
     */
    private WebElement xpathFind(AppiumDriver<WebElement> driver, IStepTarget target) {
        JSONObject object = JSON.parseObject(target.getValue(), JSONObject.class);
        String xpath = object.getString(UsingType.Key.SELECTOR_KEY);
        logger.info("拿到的xpath:{}", xpath);
        try {
            driver.manage().timeouts().implicitlyWait(waitTimeout, TimeUnit.SECONDS);
        } catch (NoSuchSessionException e) {
            throw e;
        }
        WebElement webElement = null;
        List<WebElement> elements = null;
        try {
            elements = driver.findElements(By.xpath(xpath));
        } catch (WebDriverException e) {
            logger.error("driver查找控件异常：", e);
            throw new ExecuteException("设备自动化驱动连接异常，查找控件失败");
        }
        logger.info("找到元素{}个", elements.size());
        if (!CollectionUtils.isEmpty(elements)) {   //xpath找到了
            webElement = elements.get(0);
        }
        return webElement;
    }

    public String getElementValueByOcr(IExecuteContext context, AppiumDriver<WebElement> driver, WebElement webElement) {
        String imgBase64 = null;
        try {
            imgBase64 = ocrFindCodeArea(webElement, driver, context);
        } catch (NoSuchSessionException | ExecuteException | ParamMistakeException e) {
            throw e;
        } catch (Exception e) {
            logger.error("查找区域截图失败", e);
            throw new ExecuteException("查找区域截图失败");
        }
        if (null == imgBase64) {
            throw new ExecuteException("未截取到区域");
        }
        String ocrAddress = context.getProperty(ConfigPath.OCR_GET_ALL_TEXT_NUM_KEY);
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            Map<String, Object> ocrParamMap = new HashMap<>();
            ocrParamMap.put("img_base64", imgBase64);
            ocrParamMap.put("targets", "");
            HttpEntity<Map> ocrEntity = new HttpEntity<>(ocrParamMap, headers);
            List ocrResultList = null;
            try {
                logger.info("传参：{}", JSON.toJSONString(ocrParamMap));
                ocrResultList = HttpUtils.doPost(ocrAddress, ocrEntity, List.class);
                logger.info("得到的ocr结果：{}", ocrResultList);
            } catch (Exception e) {
                logger.error("ocr失败", e);
            }
            List<String> dataList = new ArrayList<>();
            if (!CollectionUtils.isEmpty(ocrResultList)) {
                if (!CollectionUtils.isEmpty(ocrResultList)) {
                    for (Object o : ocrResultList) {
                        dataList.add(((Map) o).get("text") + "");
                    }
                }
            }
            return JSON.toJSONString(dataList);
        } catch (Exception e) {
            logger.error("请求ocr接口失败，接口地址：{}", ocrAddress, e);
            throw new ExecuteException("请求ocr识别接口失败，请查看ocr识别服务是否开启！");
        }
    }

    public String ocrFindCodeArea(WebElement webElement, AppiumDriver<WebElement> driver, IExecuteContext context) {
        String result = null;
        Rectangle rect = webElement.getRect();
        int x =  rect.getX();
        int y =  rect.getY();
        int width = rect.getWidth();
        int height = rect.getHeight();
        Map<String, Object> deviceInfo = context.getDeviceInfo();
        String resolution = (String) deviceInfo.get("resolution");
        String[] split = resolution.split("\\*");
        int screenLength = Integer.parseInt(split[0]);
        int screenWidth = Integer.parseInt(split[1]);
        logger.info("通过xpth找到元素的x：{}，y：{}， width：{}， height：{}，screenLength：{}，screenWidth：{}", x, y, width, height, screenLength,screenWidth);
        Map<String, Object> paramMap = new HashMap<>();
        if (driver instanceof IOSDriver) {
            paramMap.put("platform", "1");
        } else {
            paramMap.put("platform", "0");
        }
        paramMap.put("deviceId", driver.getCapabilities().getCapability("deviceName"));
        paramMap.put("length", width);
        paramMap.put("width", height);
        paramMap.put("resolution", resolution);
        paramMap.put("x", x);
        paramMap.put("y", y);
        paramMap.put("screenLength", screenLength);
        paramMap.put("screenWidth", screenWidth);
        logger.info("参数：{}", JSON.toJSONString(paramMap));
        HttpEntity<Map<String, Object>> entity = new HttpEntity<>(paramMap);
        String host = driver.getRemoteAddress().getHost();  //上位机地址
        String port = (String) deviceInfo.get("port");   //上位机端口
        String mobileShotAddress = context.getProperty(ConfigPath.MOBILE_SHOT_ADDRESS_KEY);
        String shotScreenAddress = String.format(ConfigPath.HTTP_FORMAT, host, port, mobileShotAddress);
        try {
            result = HttpUtils.doPost(shotScreenAddress, entity, String.class);
        } catch (Exception e) {
            logger.error("截图失败", e);
        }
        return result;
    }


}
