package com.huatek.busi.service.impl;

import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.hutool.core.net.NetUtil;
import com.huatek.busi.common.Md5Util;
import com.huatek.busi.common.SiteConstants;
import com.huatek.busi.entity.BusiArresterSubTree;
import com.huatek.busi.entity.BusiCableSubTree;
import com.huatek.busi.entity.BusiGisSubTree;
import com.huatek.busi.entity.BusiTransfromerSubTree;
import com.huatek.busi.mapper.*;
import com.huatek.torch.frame.tools.ConstantUtil;
import com.huatek.torch.frame.tools.ResultUtil;
import com.sun.corba.se.spi.ior.IdentifiableFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import com.alibaba.dubbo.config.annotation.Service;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Maps;
import com.huatek.busi.common.BusiConstant.Indicators;
import com.huatek.busi.common.SiteConstants.SiteTreeEnum;
import com.huatek.busi.common.util.DateUtil;
import com.huatek.busi.dto.BusiEqmWarningDto;
import com.huatek.busi.dto.EquipmentInfoDto;
import com.huatek.busi.service.BusiCommonService;
import com.huatek.busi.service.BusiEqmWarningService;
import com.huatek.busi.service.BusiEvaMonitorConfigService;
import com.huatek.busi.service.BusiHomePageService;
import com.huatek.busi.service.BusiSensorService;
import com.huatek.busi.service.BusiStabilityService;
import com.huatek.busi.service.BusiSubTreeService;
import com.huatek.busi.service.FailureRateService;
import com.huatek.busi.service.MeteorologicalService;
import com.huatek.busi.service.arrester.LightningrodImService;
import com.huatek.busi.service.transformer.TransformerEpaDeviationStatisticsService;
import com.huatek.busi.vo.BusiEvaMonitorUnitIndicatorsVo;
import com.huatek.busi.vo.BusiHomeInfoVo;
import com.huatek.busi.vo.BusiHomePageVo;
import com.huatek.busi.vo.BusiSensorVo;
import com.huatek.busi.vo.MeteorologicalVo;
import com.huatek.busi.vo.warning.BusiHomePageWarningVo;

import lombok.extern.slf4j.Slf4j;

/**
 * @ClassName: BusiHomePageServiceImpl
 * @FullClassPath: com.huatek.busi.service.impl.BusiHomePageServiceImpl
 * @Description: 主页面服务.
 * @author: Arno
 * @date: Jul 25, 2019 2:49:37 PM
 * @version: 1.0
 */
@Slf4j
@Component
@Service(interfaceClass = BusiHomePageService.class)
@Transactional(rollbackFor = Exception.class)
public class BusiHomePageServiceImpl implements BusiHomePageService {
    @Autowired
    private FailureRateService failureRateService;
    @Autowired
    private BusiStabilityService busiStabilityService;
    @Autowired
    private BusiEvaMonitorConfigService busiEvaMonitorConfigService;
    @Autowired
    private BusiTransfromerSubTreeMapper busiTransfromerSubTreeMapper;
    @Autowired
    private BusiGisSubTreeMapper busiGisSubTreeMapper;
    @Autowired
    private BusiArresterSubTreeMapper busiArresterSubTreeMapper;
    @Autowired
    private BusiCableSubTreeMapper busiCableSubTreeMapper;
    @Autowired
    private BusiEqmWarningService busiEqmWarningService;
    @Autowired
    private MeteorologicalService meteorologicalService;
    @Autowired
    private TransformerEpaDeviationStatisticsService transformerEpaDeviationStatisticsService;
    @Autowired
    private BusiSensorService busiSensorService;
    @Autowired
    private BusiCommonService busiCommonService;
    @Autowired
    private BusiSubTreeService busiSubTreeService;
    @Autowired
    private LightningrodImService lightningrodImService;

    @Autowired
    private BusiTransformerSensorMapper busiTransformerSensorMapper;
    @Autowired
    private BusiGisSensorMapper busiGisSensorMapper;
    @Autowired
    private BusiCableSensorMapper busiCableSensorMapper;
    @Autowired
    private BusiArresterSensorMapper busiArresterSensorMapper;

    @Value("${dangle.dat.path}")
    private String danglePath;

    @Value("${dangle.dat.ip}")
    private String ip;

    @Value("${dangle.dat.mac}")
    private String mac;

    @Override
    public List<BusiHomePageVo> findTransfromerlist(String equipmentType) {
        return busiTransfromerSubTreeMapper.findByEquipmentType(equipmentType);
    }

    @Override
    public List<BusiHomePageVo> findArresterlist(String equipmentType) {
        return busiArresterSubTreeMapper.findArresterlist(equipmentType);
    }

	@Override
    public BusiHomeInfoVo findTransfromerInfo(String mainTreeId, String subTreeId, String subEquipmentId, SiteTreeEnum siteTreeEnum,
        String equipmentType, String sensorId) {
        BusiHomeInfoVo info = new BusiHomeInfoVo();
        info.setMainTreeId(mainTreeId);
        info.setSubTreeId(subTreeId);
        info.setSubEquipmentId(subEquipmentId);
        //传感器
        String manufactor = "--", useDate = "--";
        BusiSensorVo busiSensorVo = busiSensorService.getBusiSensorVoById(siteTreeEnum, sensorId);
        if (null == busiSensorVo) {
            return info;
        }
        info.setMainTreeName(busiSensorVo.getMainTreeName());
        info.setSubTreeName(busiSensorVo.getSubTreeName());
        info.setSensorName(busiSensorVo.getSensorName());
        info.setSensorCode(busiSensorVo.getSensorCode());
        manufactor = busiSensorVo.getManufactor();
        if(busiSensorVo.getUseDate() != null) {
            useDate = busiSensorVo.getUseDate().toString();
        }
        EquipmentInfoDto equipmentInfo = busiSubTreeService.findEquipmentInfo(busiSensorVo.getSensorCode(), siteTreeEnum.getValue());
        if(equipmentInfo == null) {
            return info;
        }
        // 开始时间、结束时间
        LocalDateTime startTime = DateUtil.getMonthStartDay();
        LocalDateTime endTime = DateUtil.getMonthLastDay();
//        LocalDateTime endTime = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
        // 0. 查询配置的考评指标
        List<BusiEvaMonitorUnitIndicatorsVo> configList =
            busiEvaMonitorConfigService.findIndicatorsBySensorCode(info.getSensorCode());
        if(CollectionUtils.isEmpty(configList)) {
            return info;
        }
        Map<String, Map<String, Object>> indicatorsMap = Maps.newLinkedHashMap();
        // 1. 分表计算每个考评指标的值
        for (BusiEvaMonitorUnitIndicatorsVo vo : configList) {
            Indicators indicators = Indicators.fromValue(vo.getAttr());
            if(indicators == null) {
                log.warn("未知考评指标：{}", vo.getAttr());
                continue;
            }
            Map<String, Object> itemMap = Maps.newLinkedHashMap();
            itemMap.put("name", vo.getName());
            switch (indicators) {
                case ACCURACY:
                    //最差精度指标
                    itemMap.put("value", transformerEpaDeviationStatisticsService.getWorstEpaDeviation(info.getSensorCode()));
                    break;
                case DATA_STABILITY_MAP:
                    itemMap.put("value", busiStabilityService.findStabilityMapBySensorCode(info.getSensorCode()));
                    break;
                case DATA_STATISTICS:
                    break;
                case EUIP_SENSITIVITY:
                    break;
                case FALSE_ALARM_RATE: //误报率
                    itemMap.put("value", busiEqmWarningService.getFalseAlarmRateBySensor(info.getSensorCode(),DateUtil.getMonthStartDay(),DateUtil.getMonthLastDay()));
                    break;
                case LOSS_RATE: //数据缺失率
                    String lossRate = failureRateService.getSensorLossRate(busiSensorVo.getSensorCode(), startTime, endTime);
                    if(StringUtils.isEmpty(lossRate)) {
                        lossRate = "100";
                    }
                    itemMap.put("value", lossRate);
                    break;
                case MANUFACTOR:
                    itemMap.put("value", manufactor);
                    break;
                case NEUTRAL_POINT_CURRENT:
                    break;
                case ORIGINAL_NOISE:
                    break;
                case ORIGINAL_STABILITY_MAP:
                    break;
                case REPAIR_COUNT:
                    itemMap.put("value", busiCommonService.getSensorHalfYearRepairCount(siteTreeEnum, info.getSensorCode()));
                    break;
                case SIDE_NOISE:
                    break;
                case SIDE_STABILITY_MAP:
                    break;
                case STABILITY_MAP:
                    itemMap.put("value", busiStabilityService.findStabilityMapBySensorCode(info.getSensorCode()));
                    break;
                case USE_DATE:
                    itemMap.put("value", useDate);
                    break;
                case STATISTICAL_DATA: //落雷次数
                    itemMap.put("value", lightningrodImService.getSensorActionCount(busiSensorVo.getSensorCode(), startTime, endTime));
                    break;
            }
            indicatorsMap.put(vo.getAttr(), itemMap);
            log.debug("{}-{}-{}", vo.getName(), vo.getAttr(), itemMap);
        }
        info.setIndicatorsMap(indicatorsMap);
        return info;
    }

    @Override
    public PageInfo<BusiHomePageWarningVo> findCurrentWarningList(BusiEqmWarningDto busiEqmWarningDto) {
         return busiEqmWarningService.findCurrentWarningList(busiEqmWarningDto);
    }

    @Override
    public PageInfo<BusiHomePageWarningVo> findCurrentWarningBySensorCodeList(BusiEqmWarningDto busiEqmWarningDto) {

        return busiEqmWarningService.findCurrentWarningBySensorCodeList(busiEqmWarningDto);
    }
    @Override
    public  boolean verifyDongle() throws UnknownHostException {
        String path=danglePath;
        File file = new File(path);
        List list = new ArrayList();
        String sourse="";
        if (file.exists()) {
            try {
                //将文件的每行为一个元素添加到list中
                list = Files.readAllLines(file.toPath(), Charset.defaultCharset());
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            if (list.isEmpty()){
                return false;
            }

        }else{
            return false;
        }
        for (Object line : list) {
            sourse+=line;
        }
        String sourseNew = Md5Util.md5(Md5Util.DANGLE_CONTENT+ip+mac).toUpperCase();
        if(sourse.equals(sourseNew)){
            return true;
        }else{
            return false;
        }

    }

    @Override
    public MeteorologicalVo queryMeteorologicalInfo() {
        return meteorologicalService.queryMeteorologicalInfo("", "");
    }

    @Override
    public Map<String, List<BusiHomeInfoVo>> getIndicatorsMap( String mainTreeId, String mainEqmType) {
        Map<String, List<BusiHomeInfoVo>> map = new HashMap<>();
        // 变压器
        if (SiteConstants.MainEqmTypeEnum.BYQ.getValue().equals(mainEqmType)) {
            // 油色谱
            map.put("ysp", getDeviceTransfromerBusiHomeInfoList(mainTreeId, SiteConstants.TransfromerTreeEnum.YSP_EQM.getValue()));
            // 绕组测温
            map.put("rzcw", getDeviceTransfromerBusiHomeInfoList(mainTreeId, SiteConstants.TransfromerTreeEnum.RZCW_EQM.getValue()));
            // 局部放电
            map.put("jf", getDeviceTransfromerBusiHomeInfoList(mainTreeId, SiteConstants.TransfromerTreeEnum.JF_EQM.getValue()));
        }
        // GIS
        else if (SiteConstants.MainEqmTypeEnum.GIS.getValue().equals(mainEqmType)) {
            // sf6
            map.put("sf6", getDeviceGisBusiHomeInfoList(mainTreeId, SiteConstants.GisTreeEnum.SF6_EQM.getValue()));
            // 局放
            map.put("jf", getDeviceGisBusiHomeInfoList(mainTreeId, SiteConstants.GisTreeEnum.JF_EQM.getValue()));
        }
        // 电缆
        else if (SiteConstants.MainEqmTypeEnum.DL.getValue().equals(mainEqmType)) {
            // 电缆局放
            map.put("dljf", getDeviceDLBusiHomeInfoList(mainTreeId, SiteConstants.CableTreeEnum.DLJF_EQM.getValue()));
            // 电缆环流
            map.put("dlhl", getDeviceDLBusiHomeInfoList(mainTreeId, SiteConstants.CableTreeEnum.DLHL_EQM.getValue()));
        }
        // 避雷器
        else if (SiteConstants.MainEqmTypeEnum.BLQ.getValue().equals(mainEqmType)) {
            map.put("jy", getDeviceBlqBusiHomeInfoList(mainTreeId, SiteConstants.ArresterTreeEnum.JY_EQM.getValue()));
            map.put("rx", getDeviceBlqBusiHomeInfoList(mainTreeId, SiteConstants.ArresterTreeEnum.RX_EQM.getValue()));
        }
        // 开关柜 todo
        else if (SiteConstants.MainEqmTypeEnum.KGG.getValue().equals(mainEqmType)) {
        }
        // 发电机 todo
        else if (SiteConstants.MainEqmTypeEnum.FDJ.getValue().equals(mainEqmType)) {
        }
        return map;
    }


    /**
     * 获取变压器下所有某一装置的误报率、数据缺失率对象
     *
     * @param mainTreeId 主设备树id
     * @param deviceType 装置类型编码
     */
    List<BusiHomeInfoVo> getDeviceTransfromerBusiHomeInfoList(String mainTreeId, String deviceType) {
        List<BusiHomeInfoVo> busiHomeInfoVoList = new ArrayList<>();
        List<BusiTransfromerSubTree> subTreeList = busiTransfromerSubTreeMapper.findListByEquipmentIdAndType(mainTreeId, deviceType);
        if (!ObjectUtils.isEmpty(subTreeList)) {
            for (BusiTransfromerSubTree subTree : subTreeList) {
                List<BusiSensorVo> busiSensorVoList = busiTransformerSensorMapper.querySensorByEquipmentId(subTree.getId());
                if (!ObjectUtils.isEmpty(busiSensorVoList)) {
                    for (BusiSensorVo sensor : busiSensorVoList) {
                        BusiHomeInfoVo busiHomeInfoVo = findTransfromerInfo(mainTreeId, subTree.getId(), null, SiteTreeEnum.BYQ, deviceType, sensor.getId());
                        if (!ObjectUtils.isEmpty(busiHomeInfoVo)) {
                            busiHomeInfoVoList.add(busiHomeInfoVo);
                        }
                    }
                }
            }
        }
        return busiHomeInfoVoList;
    }

    /**
     * 获取GIS下所有某一装置的误报率、数据缺失率对象
     *
     * @param mainTreeId 主设备树id
     * @param deviceType 装置类型编码
     */
    List<BusiHomeInfoVo> getDeviceGisBusiHomeInfoList(String mainTreeId, String deviceType) {
        List<BusiHomeInfoVo> busiHomeInfoVoList = new ArrayList<>();
        List<BusiGisSubTree> subTreeList = busiGisSubTreeMapper.findListByEquipmentIdAndType(mainTreeId, deviceType);
        if (!ObjectUtils.isEmpty(subTreeList)) {
            for (BusiGisSubTree subTree : subTreeList) {
                List<BusiSensorVo> busiSensorVoList = busiGisSensorMapper.querySensorByEquipmentId(subTree.getId());
                if (!ObjectUtils.isEmpty(busiSensorVoList)) {
                    for (BusiSensorVo sensor : busiSensorVoList) {
                        if (ObjectUtils.isEmpty(sensor.getSensorCode())) {
                            continue;
                        }
                        BusiHomeInfoVo busiHomeInfoVo = findTransfromerInfo(mainTreeId, subTree.getId(), null, SiteTreeEnum.GIS, deviceType, sensor.getId());
                        if (!ObjectUtils.isEmpty(busiHomeInfoVo)) {
                            busiHomeInfoVoList.add(busiHomeInfoVo);
                        }
                    }
                }
            }
        }
        return busiHomeInfoVoList;
    }

    /**
     * 获取电缆下所有某一装置的误报率、数据缺失率对象
     *
     * @param mainTreeId 主设备树id
     * @param deviceType 装置类型编码
     */
    List<BusiHomeInfoVo> getDeviceDLBusiHomeInfoList(String mainTreeId, String deviceType) {
        List<BusiHomeInfoVo> busiHomeInfoVoList = new ArrayList<>();
        List<BusiCableSubTree> subTreeList = busiCableSubTreeMapper.findListByEquipmentIdAndType(mainTreeId, deviceType);
        if (!ObjectUtils.isEmpty(subTreeList)) {
            for (BusiCableSubTree subTree : subTreeList) {
                List<BusiSensorVo> busiSensorVoList = busiCableSensorMapper.querySensorByEquipmentId(subTree.getId());
                if (!ObjectUtils.isEmpty(busiSensorVoList)) {
                    for (BusiSensorVo sensor : busiSensorVoList) {
                        if (ObjectUtils.isEmpty(sensor.getSensorCode())) {
                            continue;
                        }
                        BusiHomeInfoVo busiHomeInfoVo = findTransfromerInfo(mainTreeId, subTree.getId(), null, SiteTreeEnum.GIS, deviceType, sensor.getId());
                        if (!ObjectUtils.isEmpty(busiHomeInfoVo)) {
                            busiHomeInfoVoList.add(busiHomeInfoVo);
                        }
                    }
                }
            }
        }
        return busiHomeInfoVoList;
    }

    /**
     * 获取避雷器下所有某一装置的误报率、数据缺失率对象
     *
     * @param mainTreeId 主设备树id
     * @param deviceType 装置类型编码
     */
    List<BusiHomeInfoVo> getDeviceBlqBusiHomeInfoList(String mainTreeId, String deviceType) {
        List<BusiHomeInfoVo> busiHomeInfoVoList = new ArrayList<>();
        List<BusiArresterSubTree> subTreeList = busiArresterSubTreeMapper.findListByEquipmentIdAndType(mainTreeId, deviceType);
        if (!ObjectUtils.isEmpty(subTreeList)) {
            for (BusiArresterSubTree subTree : subTreeList) {
                List<BusiSensorVo> busiSensorVoList = busiArresterSensorMapper.querySensorByEquipmentId(subTree.getId());
                if (!ObjectUtils.isEmpty(busiSensorVoList)) {
                    for (BusiSensorVo sensor : busiSensorVoList) {
                        if (ObjectUtils.isEmpty(sensor.getSensorCode())) {
                            continue;
                        }
                        BusiHomeInfoVo busiHomeInfoVo = findTransfromerInfo(mainTreeId, subTree.getId(), null, SiteTreeEnum.BLQ, deviceType, sensor.getId());
                        if (!ObjectUtils.isEmpty(busiHomeInfoVo)) {
                            busiHomeInfoVoList.add(busiHomeInfoVo);
                        }
                    }
                }
            }
        }
        return busiHomeInfoVoList;
    }

    /**
     * 获取开关柜下所有某一装置的误报率、数据缺失率对象
     *
     * @param mainTreeId 主设备树id
     * @param deviceType 装置类型编码
     */
    List<BusiHomeInfoVo> getDeviceKggBusiHomeInfoList(String mainTreeId, String deviceType) {
        List<BusiHomeInfoVo> busiHomeInfoVoList = new ArrayList<>();
        List<BusiTransfromerSubTree> subTreeList = busiTransfromerSubTreeMapper.findListByEquipmentIdAndType(mainTreeId, deviceType);
        if (!ObjectUtils.isEmpty(subTreeList)) {
            for (BusiTransfromerSubTree subTree : subTreeList) {
                List<BusiSensorVo> busiSensorVoList = busiTransformerSensorMapper.querySensorByEquipmentId(subTree.getId());
                if (!ObjectUtils.isEmpty(busiSensorVoList)) {
                    for (BusiSensorVo sensor : busiSensorVoList) {
                        BusiHomeInfoVo busiHomeInfoVo = findTransfromerInfo(mainTreeId, subTree.getId(), null, SiteTreeEnum.CW, deviceType, sensor.getId());
                        if (!ObjectUtils.isEmpty(busiHomeInfoVo)) {
                            busiHomeInfoVoList.add(busiHomeInfoVo);
                        }
                    }
                }
            }
        }
        return busiHomeInfoVoList;
    }
}