package com.jpsoft.shinestar.modules.hikvision.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.jpsoft.ehome.common.EHomeResult;
import com.jpsoft.ehome.config.EHomeParamConfig;
import com.jpsoft.ehome.device.EHomeDeviceManager;
import com.jpsoft.ehome.device.EHomeSDK;
import com.jpsoft.ehome.xml.InputXmlSection;
import com.jpsoft.shinestar.config.HikvisionAcsConfig;
import com.jpsoft.shinestar.modules.base.entity.DeviceInfo;
import com.jpsoft.shinestar.modules.base.entity.PersonInfo;
import com.jpsoft.shinestar.modules.base.service.DeviceInfoService;
import com.jpsoft.shinestar.modules.base.service.PersonDeviceRelationService;
import com.jpsoft.shinestar.modules.base.service.PersonInfoService;
import com.jpsoft.shinestar.modules.hikvision.service.IEHomeService;
import com.jpsoft.shinestar.modules.pacs.dto.IsPersonExistVo;
import com.jpsoft.shinestar.modules.pacs.dto.PacsMsgResult;
import com.jpsoft.shinestar.modules.pacs.dto.PacsResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
public class EHomeServiceImpl implements IEHomeService {
    @Autowired
    private DeviceInfoService deviceInfoService;

    @Autowired
    private PersonInfoService personInfoService;

    @Autowired
    private HikvisionAcsConfig acsConfig;

    @Autowired
    private PersonDeviceRelationService personDeviceRelationService;

    @Autowired
    private EHomeSDK eHomeSDK;

    @Autowired
    private EHomeParamConfig eHomeParamConfig;

    @Value("${spring.profiles.active}")
    private String profile;

    @Override
    public boolean keepAlive(String deviceId) {
        DeviceInfo deviceInfo = deviceInfoService.get(deviceId);

        Integer loginID = EHomeDeviceManager.get(deviceInfo.getDeviceNo());

        boolean result = false;

        if(loginID!=null) {
            try {
                EHomeResult<String> eHomeResult = eHomeSDK.deviceXMLConfig(loginID, "GETDEVICECONFIG", InputXmlSection.getNetParam());
                result = eHomeResult.isSuccess();
            } catch (Exception ex) {
                result = false;
                log.error(ex.getMessage(), ex);
            }
        }

        return result;
    }

    @Override
    public boolean reboot(String deviceId) {
        DeviceInfo deviceInfo = deviceInfoService.get(deviceId);

        Integer loginID = EHomeDeviceManager.get(deviceInfo.getDeviceNo());

        boolean result = false;

        try {
            EHomeResult<String> eHomeResult = eHomeSDK.remoteControl(loginID,InputXmlSection.rebootXml());
            result = eHomeResult.isSuccess();
        }
        catch (Exception ex){
            result = false;
            log.error(ex.getMessage(),ex);
        }

        return result;
    }

    @Override
    public PacsResult addPersonToDevice(Long personId, String deviceId) {
        PacsResult pacsResult = new PacsResult();

        try {
            DeviceInfo deviceInfo = deviceInfoService.get(deviceId);
            PersonInfo personInfo = personInfoService.get(personId);

            Integer loginID = EHomeDeviceManager.get(deviceInfo.getDeviceNo());

            if (loginID == null) {
                throw new Exception("设备" + deviceInfo.getDeviceNo() + "不在线!");
            }

            String cardNo = String.valueOf(personId);

            //1.下发卡号 SetCardCfg
            EHomeResult<String> eHomeResult = eHomeSDK.deviceXMLConfig(loginID, "SETDEVICECONFIG",
                    InputXmlSection.setCardConfigXml(cardNo, 1, cardNo, personInfo.getName()));

            if (!eHomeResult.isSuccess()) {
                throw new Exception("下发卡号失败!" + eHomeResult.getMessage());
            }

            //2.卡号开权限 SetCardRightCfg
            eHomeResult = eHomeSDK.deviceXMLConfig(loginID, "SETDEVICECONFIG", InputXmlSection.cardRightConfigXml(cardNo));

            if (!eHomeResult.isSuccess()) {
                throw new Exception("卡号权限设置失败!" + eHomeResult.getMessage());
            }

            //3.从oss中下载然后上传人脸照片到KMS,文件名字不能有中文
            //http://rccs.oss-cn-hangzhou.aliyuncs.com/smart/person/2020/4/13162626598.jpg?x-oss-process=image/resize,m_lfit,h_400,w_400
            URL url = new URL(personInfo.getFaceImageUrl() + "?x-oss-process=image/resize,m_lfit,h_400");

            //创建连接
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(5000);

            InputStream faceImageInput = conn.getInputStream();

            //将oss照片上传到KMS
            //荆楚云docker容器中无法访问服务器外网IP
            String remoteIP = eHomeParamConfig.getRemoteIP();

            if("production".equals(profile)){
                remoteIP = "127.0.0.1";
            }

            eHomeResult = eHomeSDK.clientUpload(remoteIP,
                    eHomeParamConfig.getPictureServerTcpPort(),
                    faceImageInput, eHomeParamConfig.getUrlPrefix());

            faceImageInput.close();

            if (!eHomeResult.isSuccess()) {
                throw new Exception("上传人脸照片到KMS失败!" + eHomeResult.getMessage());
            }

            //4.下发人脸照片到设备 SetFaceParamCfg
            String facePicUrl = eHomeResult.getData();

            eHomeResult = eHomeSDK.ptXMLConfig("POST", loginID,
                    "/ISAPI/AccessControl/SetFaceParamCfg", null, InputXmlSection.faceParamCfgXml(cardNo, facePicUrl));

            Boolean success = eHomeResult.isSuccess();
            String message = eHomeResult.getMessage();
            String data = eHomeResult.getData();

            if (success) {
                personDeviceRelationService.updateIsBound(personInfo.getId(), deviceInfo.getId(), true);
            }

            pacsResult.setSuccess(success);
            pacsResult.setMsg(deviceInfo.getAliasName() + ":" + message);
            pacsResult.setData(data);
        }
        catch (Exception ex){
            pacsResult.setSuccess(false);
            pacsResult.setMsg(ex.getMessage());

            log.error(ex.getMessage(),ex);
        }

        return pacsResult;
    }

    @Override
    public List<IsPersonExistVo> existPersonInDevice(List<Long> personIdList, DeviceInfo deviceInfo) {
        List<IsPersonExistVo> voList = new ArrayList<>();

        Integer loginID = EHomeDeviceManager.get(deviceInfo.getDeviceNo());

        if (loginID!=null) {
            for (int i = 0; i < personIdList.size(); i++) {
                long personId = personIdList.get(i);
                String cardNo = String.valueOf(personId);

                IsPersonExistVo vo = new IsPersonExistVo();

                try {
                    EHomeResult<String> personExistResult = eHomeSDK.ptXMLConfig("POST", loginID,
                            "/ISAPI/AccessControl/GetFaceParamCfg", null, InputXmlSection.getFaceParamConfigXml(cardNo));

                    vo.setPersonId(personId);
                    vo.setIsPersonExist(personExistResult.isSuccess());
                }
                catch (Exception ex){
                    vo.setIsPersonExist(false);
                    vo.setPersonId(personId);

                    log.error(ex.getMessage(),ex);
                }

                voList.add(vo);
            }
        }

        return voList;
    }

    @Override
    public PacsMsgResult deletePersonFromDevice(Long personId, String deviceId) {
        DeviceInfo deviceInfo = deviceInfoService.get(deviceId);
        PersonInfo personInfo = personInfoService.get(personId);

        Integer loginID = EHomeDeviceManager.get(deviceInfo.getDeviceNo());
        String cardNo = String.valueOf(personId);

        PacsMsgResult pacsMsgResult = new PacsMsgResult();

        pacsMsgResult.setAliasName(deviceInfo.getAliasName());
        pacsMsgResult.setPersonName(personInfo.getName());
        pacsMsgResult.setPersonId(personId);
        pacsMsgResult.setDeviceId(deviceId);

        try {
            EHomeResult<String> eHomeResult = eHomeSDK.deviceXMLConfig(loginID, "SETDEVICECONFIG",
                    InputXmlSection.setCardConfigXml(cardNo, 0, null, null));

            pacsMsgResult.setSuccess(eHomeResult.isSuccess());
            pacsMsgResult.setMsg(eHomeResult.getMessage());
        }
        catch (Exception ex){
            pacsMsgResult.setSuccess(false);
            pacsMsgResult.setMsg(ex.getMessage());

            log.error(ex.getMessage(),ex);
        }

        return pacsMsgResult;
    }

    @Override
    public PacsMsgResult remoteOpen(String deviceId) {
        PacsMsgResult pacsMsgResult = new PacsMsgResult();
        DeviceInfo deviceInfo = deviceInfoService.get(deviceId);

        pacsMsgResult.setAliasName(deviceInfo.getAliasName());
        pacsMsgResult.setDeviceId(deviceId);

        Integer loginID = EHomeDeviceManager.get(deviceInfo.getDeviceNo());

        try {
            EHomeResult<String> eHomeResult = eHomeSDK.remoteControl(loginID, InputXmlSection.remoteControlXml("1","OPEN"));
            pacsMsgResult.setSuccess(eHomeResult.isSuccess());
        }
        catch (Exception ex){
            pacsMsgResult.setSuccess(false);
            pacsMsgResult.setMsg(ex.getMessage());

            log.error(ex.getMessage(),ex);
        }

        return pacsMsgResult;
    }

    /**
     * 门禁设备不支持远程修改IP和端口
     * @param deviceInfo
     * @param newAddress
     * @param newPort
     * @return
     */
    @Override
    public PacsMsgResult updateDeviceServerConfig(DeviceInfo deviceInfo, String newAddress, String newPort) {
        PacsMsgResult pacsMsgResult = new PacsMsgResult();

        pacsMsgResult.setAliasName(deviceInfo.getAliasName());
        pacsMsgResult.setDeviceId(deviceInfo.getId());

        Integer loginID = EHomeDeviceManager.get(deviceInfo.getDeviceNo());

        try {
            EHomeResult<String> eHomeResult = eHomeSDK.remoteControl(loginID,
                    InputXmlSection.updateServerConfigXml(deviceInfo.getDeviceNo(),newAddress,newPort));

            pacsMsgResult.setSuccess(eHomeResult.isSuccess());
        }
        catch (Exception ex){
            pacsMsgResult.setSuccess(false);
            pacsMsgResult.setMsg(ex.getMessage());

            log.error(ex.getMessage(),ex);
        }

        return pacsMsgResult;
    }
}
