package net.northking.cctp.se.device.service.impl;

import lombok.extern.slf4j.Slf4j;
import net.northking.cctp.common.http.ResultWrapper;
import net.northking.cctp.element.core.exception.ExecuteException;
import net.northking.cctp.se.config.AtuServerConfig;
import net.northking.cctp.se.device.bean.DeviceInfo;
import net.northking.cctp.se.device.bean.MobileDeviceConnection;
import net.northking.cctp.se.device.bean.PCDeviceConnection;
import net.northking.cctp.se.device.service.DeviceConnection;
import net.northking.cctp.se.device.service.DeviceConnectionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Component
public class DeviceConnectionManager implements DeviceConnectionService {
    private Map<String,DeviceConnection> deviceConnectionMap = new ConcurrentHashMap<>();

    @Autowired
    private AtuServerConfig atuServerConfig;

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 根据设备token从服务端获取设备信息
     * @param deviceToken
     * @return
     */
    public DeviceInfo loadDeviceInfo(String deviceToken) {
        String url = atuServerConfig.getServerUrl() + atuServerConfig.getDeviceInfoPath() + deviceToken;
        ResponseEntity<Map> resEntity = restTemplate.getForEntity(url, Map.class);
        Map resultBody = resEntity.getBody();
        DeviceInfo deviceInfo = new DeviceInfo();
        if (resultBody != null && (boolean)resultBody.get("success") && resultBody.get("data") != null) { // 请求成功，获取到设备信息
            Map data = (Map) resultBody.get("data");
            if (data.get("cdMobileDevice") != null) {   // 是移动设备
                deviceInfo.setMobile(true);
                deviceInfo.setConnectAddress(((Map)(data.get("cdDeviceCtrl"))).get("ctrlIp").toString());   // 上位机ip
                deviceInfo.setDeviceId(((Map)(data.get("cdMobileDevice"))).get("id").toString());   // 设备id
                deviceInfo.setPlatform(((Map)(data.get("cdMobileDevice"))).get("platform").toString());
                deviceInfo.setSystemVersion(((Map)(data.get("cdMobileDevice"))).get("platformVersion").toString());
                deviceInfo.setResolution(((Map)(data.get("cdDeviceModel"))).get("resolution").toString());
                deviceInfo.setPort(((Map)(data.get("cdDeviceCtrl"))).get("ctrlPort").toString());
                if ("1".equals(deviceInfo.getPlatform())) {  //ios
                    Map deviceMap = (Map) data.get("deviceInfo");
                    Object wdaUrl = deviceMap.get("wdaUrl");
                    if (null != wdaUrl) {
                        deviceInfo.setWdaAddress(wdaUrl + "");
                    }
                } else if ("0".equals(deviceInfo.getPlatform())){   //android
                    Map deviceMap = (Map) data.get("deviceInfo");
                    Object forwardPort = deviceMap.get("forwardPort");
                    log.debug("拿到设备【{}】在上位机用于adb转发的端口：{}",deviceInfo.getDeviceId(),forwardPort);
                    deviceInfo.setForwardPort(Integer.parseInt(forwardPort+""));
                }
            } else {    // pc设备
                deviceInfo.setMobile(false);
                Map pcInfo = (Map) (data.get("cdPcDevice"));
                deviceInfo.setConnectAddress(pcInfo.get("ipAddr").toString() + ":5589");
                deviceInfo.setDeviceId(pcInfo.get("id").toString());
                if (null == deviceInfo.getOtherInfo()) {
                    deviceInfo.setOtherInfo(new HashMap<>());
                }
                deviceInfo.getOtherInfo().put("width", pcInfo.get("width") != null ? pcInfo.get("width").toString():"1366");
                deviceInfo.getOtherInfo().put("height", pcInfo.get("height") != null ? pcInfo.get("height").toString():"768");
                // 增加查询被测系统的服务地址
                deviceInfo.getOtherInfo().put("testSysAddress", atuServerConfig.getServerUrl() + atuServerConfig.getTestSysUrl());
				// 增加获取PC设备windows账号密码，用于任务执行的时候自动解锁
                deviceInfo.getOtherInfo().put("userName", data.get("account") != null ? data.get("account").toString() : null);
                deviceInfo.getOtherInfo().put("password", data.get("pwd") != null ? data.get("pwd").toString() : null);
            }
        }
        return deviceInfo;
    }



    @Override
    public DeviceConnection createDeviceConnection(String deviceToken) throws Exception {
        DeviceInfo deviceInfo = loadDeviceInfo(deviceToken);
        DeviceConnection deviceConnection = null;
        if (deviceInfo.isMobile()){ // 移动
            Map<String, String> otherInfo = deviceInfo.getOtherInfo();
            if (null == otherInfo) {
                otherInfo = new HashMap<>();
            }
            //todo:直接从设备信息里面拿
            otherInfo.put("appiumPort", atuServerConfig.getAppiumPort());
            otherInfo.put("appiumContextPath", atuServerConfig.getAppiumContextPath());
            deviceInfo.setOtherInfo(otherInfo);
            deviceConnection = new MobileDeviceConnection(deviceToken,deviceInfo);


        }else{  // pc脚本
            deviceConnection = new PCDeviceConnection(deviceToken,deviceInfo);
        }
        deviceConnectionMap.put(deviceInfo.getDeviceId(),deviceConnection);
        return deviceConnection;
    }



    @Override
    public void closeDeviceConnection(String deviceId) {
       DeviceConnection deviceConnection = deviceConnectionMap.remove(deviceId);
       if (deviceConnection!=null){
           deviceConnection.close();
           String deviceToken = deviceConnection.getDeviceToken();
           releaseDevice(deviceToken);
       }
    }


    /**
     * 调用服务端释放设备
     * @param deviceToken
     */
    private void releaseDevice(String deviceToken){
        log.info("Release device by deviceToken[{}]",deviceToken);
        // 释放设备
        String releaseUrl = atuServerConfig.getServerUrl() + atuServerConfig.getDeviceReleasePath() + deviceToken;
        try {
            ResponseEntity<ResultWrapper> resultEntity = restTemplate.getForEntity(releaseUrl, ResultWrapper.class);
            if (HttpStatus.OK.equals(resultEntity.getStatusCode())) {
                ResultWrapper body = resultEntity.getBody();
                if (body.isSuccess()) {
                    if ((boolean) body.getData()) {
                        log.info("设备退出成功。。。。。");
                        return;
                    }
                }
            }
            //todo:先报错，后面做容错处理
            throw new ExecuteException("退出设备失败");
        } catch (RestClientException e) {
            log.error("释放设备【{}】失败", deviceToken, e);
        } catch (ExecuteException e) {
            throw e;
        }
    }
}
