package net.northking.cctp.element.mobile.utils.phoneUtils;

import com.alibaba.fastjson.JSON;
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.TouchAction;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.ios.IOSDriver;
import io.appium.java_client.touch.LongPressOptions;
import io.appium.java_client.touch.offset.PointOption;
import net.northking.cctp.element.core.IExecuteContext;
import net.northking.cctp.element.core.ITestTarget;
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.entity.PointMessage;
import org.openqa.selenium.Capabilities;
import org.openqa.selenium.Point;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WebElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.net.URI;
import java.net.URISyntaxException;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

public class HandleUtils {

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

    private static final String HTTP_FORMAT_STR = "http://%s:%s/%s";

    public static void click(IExecuteContext context,AppiumDriver<WebElement> driver, PointMessage point) {
        Double x = new Integer(point.getX()).doubleValue();
        Double y = new Integer(point.getY()).doubleValue();
        if (point.isExchange()) {
            if (driver instanceof IOSDriver) {
                Double scale = IosUtil.getWindowsSize(context,driver);
                x = x / scale;
                y = y / scale;
            }
        }
        logger.info("未偏移前点击坐标位置，x:{},y:{}", x, y);
        logger.info("偏移x:{},y:{}",point.getxMove(),point.getyMove());
        x = x + point.getxMove();
        y = y + point.getyMove();


        logger.info("偏移后点击坐标位置，x:{},y:{}", x, y);
        try {
            new TouchAction<>(driver).tap(PointOption.point(x.intValue(), y.intValue())).perform();  //执行点击
        } catch (WebDriverException e) {
            logger.warn("driver抽了风。。。。。。,等待重新执行一次",e);
            try {
                Thread.sleep(1500);
            } catch (InterruptedException interruptedException) {
                return;
            }
            new TouchAction<>(driver).tap(PointOption.point(x.intValue(), y.intValue())).perform();  //执行点击
        }

    }

    public static void clickPassword(AppiumDriver<WebElement> driver, PointMessage point, Integer scale) {
        logger.debug("偏移后点击坐标位置，x:{},y:{}", point.getX(), point.getY());
        try {
            new TouchAction<>(driver).tap(PointOption.point(point.getX(), point.getY())).perform();  //执行点击
        } catch (WebDriverException e) {
            logger.warn("driver抽了风。。。。。。,等待重新执行一次",e);
            try {
                Thread.sleep(1500);
            } catch (InterruptedException interruptedException) {
                return;
            }
            new TouchAction<>(driver).tap(PointOption.point(point.getX(), point.getY())).perform();  //执行点击
        }

    }


    public static void longPress(IExecuteContext context,AppiumDriver<WebElement> driver, PointMessage point) {
        Duration duration = Duration.ofMillis(3000);
        TouchAction action = new TouchAction(driver);
        LongPressOptions longPressOptions = new LongPressOptions();
        Double x = new Integer(point.getX()).doubleValue();
        Double y = new Integer(point.getY()).doubleValue();
        if (point.isExchange()) {
            if (driver instanceof IOSDriver) {
                Double scale = IosUtil.getWindowsSize(context,driver);
                x = x / scale;
                y = y / scale;
            }
        }
        longPressOptions.withDuration(duration).withPosition(PointOption.point(new Point(x.intValue(), y.intValue())));
        action.longPress(longPressOptions).release().perform();
    }

    public static void monkeyTest(
            IExecuteContext context,
            AppiumDriver<WebElement> driver,
            Long execNum, String packageName, Integer seed, Long throttle, Integer touch,
            Integer montion, Integer pinchroom, Integer trackball, Integer ratation, Integer nav,
            Integer majornav, Integer syskeys, Integer appswitch, Integer flip, Integer anyevent,
            Boolean ignoreCrashes, Boolean ignoreTimeouts, Boolean ignoreNativeCrashes) {
        if (driver instanceof AndroidDriver) {
            Capabilities capabilities = driver.getCapabilities();
            String deviceId = (String) capabilities.getCapability("deviceName");
            String host = driver.getRemoteAddress().getHost();
            Map<String, Object> deviceInfo = context.getDeviceInfo();
            String port = (String) deviceInfo.get("port");
            if (!StringUtils.hasText(packageName)) {
                ITestTarget[] testTarget = context.getTestTarget();
                packageName = (String) testTarget[0].getTarget().get("appPackage");
            }
            StringBuilder shellBuilder = new StringBuilder("adb -s " + deviceId + " shell monkey -p " + packageName + " -v -v -v");
            //设置monkey参数
            logger.info("throttle = {} ", throttle);
            if (throttle == null || throttle < 300) {
                throttle = 300L;
            }
            Integer totalPercent = extracted(seed, throttle, touch, montion, pinchroom, trackball, ratation, nav, majornav, syskeys, appswitch, flip, anyevent, ignoreCrashes, ignoreTimeouts, ignoreNativeCrashes, shellBuilder);
            if (totalPercent > 100) {
                throw new ExecuteException("事件百分比的总和不能超过100%");
            }
            String shell = shellBuilder.toString() + " " + execNum;
            logger.info("执行的monkey命令：{}", shell);
            Map<String, String> param = new HashMap<>();
            param.put("shell", shell);
            SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
            factory.setConnectTimeout(15000);
            Long readTimeOut = execNum * throttle;
            factory.setReadTimeout(readTimeOut.intValue() + 5000);   //次数与每次间隔时间，设置请求的超时时间
            RestTemplate restTemplate = new RestTemplate(factory);
            HttpEntity<Map> httpEntity = new HttpEntity<>(param, null);
            String execShellPath = context.getProperty(ConfigPath.EXEC_SHELL_PATH, "engine/execShell");
            try {
                URI uri = new URI(String.format(HTTP_FORMAT_STR, host, port, execShellPath));
                restTemplate.exchange(uri, HttpMethod.POST, httpEntity, String.class);
            } catch (URISyntaxException e) {
                logger.error("上位机执行shell命令地址有误,地址：{}，错误:{}", execShellPath, e);
                throw new ParamMistakeException(String.format("上位机执行shell命令地址[%s]有误", execShellPath));
            } catch (Exception e) {
                logger.error("上位机执行shell命令失败,地址：{},参数:{},错误:{}", execShellPath, JSON.toJSONString(param), e);
                throw new ParamMistakeException("monkey测试失败");
            }
            /*long startTime = System.currentTimeMillis();
            long endTime;
            long restTime = timeout;
            long throttleDefine = throttle;
            Runtime runtime = Runtime.getRuntime();
            while (true) {
                long time = (restTime * 1000) / throttleDefine + 1;
                shell = shell + " " + time;
                try {
                    logger.info("执行adb命令：===== {}",shell);
                    Process exec = runtime.exec(shell);
                    exec.waitFor();
                    logger.info("执行完adb命令：===== {}",shell);
                    shell = shell.substring(0, shell.lastIndexOf(" "));  //初始化命令
                    logger.info("初始化命令之后：=====>{}",shell);
                    endTime = System.currentTimeMillis();
                    long spend = (endTime - startTime) / 1000;
                    logger.info("spend = {}",spend);
                    logger.info("timeout = {}",timeout);
                    if (spend >= timeout) {
                        exec.destroy();
                        break;
                    }
                    restTime = timeout - spend;
                } catch (IOException | InterruptedException e) {
                    logger.error("monkey初始化错误",e);
                    throw new ParamException("monkey初始化错误");
                }
            }*/
        } else if (driver instanceof IOSDriver) {

        }
    }

    private static Integer extracted(Integer seed, Long throttle, Integer touch, Integer montion, Integer pinchroom, Integer trackball, Integer ratation, Integer nav, Integer majornav, Integer syskeys, Integer appswitch, Integer flip, Integer anyevent, Boolean ignoreCrashes, Boolean ignoreTimeouts, Boolean ignoreNativeCrashes, StringBuilder shell) {
        Integer total = 0;
        if (null != seed && seed > 0) {
            shell.append(" -s " + seed);
        }
        if (null != throttle && throttle > 300) {
            shell.append(" --throttle " + throttle);
        } else {
            throttle = 300L;
            shell.append(" --throttle 300");
        }
        if (null != touch && touch > 0) {
            total += touch;
            shell.append(" --pct-touch " + touch);
        }
        if (null != montion && montion > 0) {
            total += montion;
            shell.append(" --pct-motion " + montion);
        }
        if (null != pinchroom && pinchroom > 0) {
            total += pinchroom;
            shell.append(" --pct-pinchzoom " + pinchroom);
        }
        if (null != trackball && trackball > 0) {
            total += trackball;
            shell.append(" --pct-trackball " + trackball);
        }
        if (null != ratation && ratation > 0) {
            total += ratation;
            shell.append(" --pct-rotation " + ratation);
        }
        if (null != nav && nav > 0) {
            total += nav;
            shell.append(" --pct-nav " + nav);
        }
        if (null != majornav && majornav > 0) {
            total += majornav;
            shell.append(" --pct-majornav " + majornav);
        }
        if (null != syskeys && syskeys > 0) {
            total += syskeys;
            shell.append(" --pct-syskeys " + syskeys);
        }
        if (null != appswitch && appswitch > 0) {
            total += appswitch;
            shell.append(" --pct-appswitch " + appswitch);
        }
        if (null != flip && flip > 0) {
            total += flip;
            shell.append(" --pct-flip " + flip);
        }
        if (null != anyevent && anyevent > 0) {
            total += anyevent;
            shell.append(" --pct-anyevent " + anyevent);
        }
        if (null != ignoreCrashes && ignoreCrashes) {
            shell.append(" --ignore-crashes ");
        }
        if (null != ignoreTimeouts && ignoreTimeouts) {
            shell.append(" --ignore-timeouts ");
        }
        if (null != ignoreNativeCrashes && ignoreNativeCrashes) {
            shell.append(" --ignore-native-crashes ");
        }
        return total;
    }
}
