package com.huatek.busi.service.impl.capacitance;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.huatek.busi.common.BusiConstant.EqType;
import com.huatek.busi.common.BusiConstant.GzType;
import com.huatek.busi.common.SiteConstants.ArresterTreeEnum;
import com.huatek.busi.common.SiteConstants.ExternalTypeEnum;
import com.huatek.busi.common.SiteConstants.SiteTreeEnum;
import com.huatek.busi.common.SiteConstants.TransfromerTreeEnum;
import com.huatek.busi.common.util.DecimalUtil;
import com.huatek.busi.common.util.FieldUtil;
import com.huatek.busi.common.util.TimeUtil;
import com.huatek.busi.common.util.Tools;
import com.huatek.busi.dto.CapacitanceEquipmentImStatisticsDto;
import com.huatek.busi.dto.EquipmentInfoDto;
import com.huatek.busi.dto.curve.BaseCurveQueryDto;
import com.huatek.busi.dto.curve.PointItemDto;
import com.huatek.busi.entity.BusiEqmWarning;
import com.huatek.busi.entity.BusiOnlineMonitorData;
import com.huatek.busi.entity.BusiSiteTree;
import com.huatek.busi.entity.CapacitanceEquipmentIm;
import com.huatek.busi.entity.CapacitanceEquipmentInsulationMonitorThreshold;
import com.huatek.busi.mapper.CapacitanceEquipmentImMapper;
import com.huatek.busi.service.BusiSiteTreeService;
import com.huatek.busi.service.IecBydworkParamService;
import com.huatek.busi.service.capacitance.CapacitanceEquipmentImCacheService;
import com.huatek.busi.service.capacitance.CapacitanceEquipmentImService;
import com.huatek.busi.service.impl.cac.AbstractCacEtlService;
import com.huatek.busi.service.threshold.CapacitanceEquipmentInsulationMonitorThresholdService;
import com.huatek.busi.vo.CapacitanceEquipmentImStatisticsVo;
import com.huatek.busi.vo.CapacitanceEquipmentImVo;
import com.huatek.busi.vo.curve.PointItemVo;
import com.huatek.busi.vo.monitor.BusiOnlineMonitorDataVo;
import com.huatek.busi.vo.stability.CapacitanceEquipmentImStabilityVo;
import com.huatek.busi.vo.warning.BusiCapaItemVo;
import com.huatek.busi.vo.warning.BusiCapaItemVo.BusiCapaItemVoBuilder;
import com.huatek.busi.vo.warning.BusiCapaVo;
import com.huatek.torch.frame.exception.OwlException;
import com.huatek.torch.frame.tools.ConstantUtil;
import com.huatek.torch.frame.tools.ResultUtil;

import lombok.extern.slf4j.Slf4j;

/**
 * 变压器容性设备：022001 ServiceImpl
 *
 * @author anker_cheng
 * @date Jun 26, 2019 1:11:48 PM
 */
@Slf4j
@Component
@Service(interfaceClass = CapacitanceEquipmentImService.class)
@Transactional(rollbackFor = Exception.class)
public class CapacitanceEquipmentImServiceImpl extends AbstractCacEtlService<CapacitanceEquipmentIm>
    implements CapacitanceEquipmentImService {
    @Autowired
    private CapacitanceEquipmentImMapper capacitanceEquipmentImMapper;
    // @Autowired
    // private CapacitanceEquipmentImDao capacitanceEquipmentImDao;

    @Reference(check = false)
    private IecBydworkParamService iecBydworkParamService;
    @Reference(check = false)
    private BusiSiteTreeService busiSiteTreeService;
    @Reference(check = false)
    private CapacitanceEquipmentImCacheService capacitanceEquipmentImCacheService;
    @Reference(check = false)
    private CapacitanceEquipmentInsulationMonitorThresholdService capacitanceEquipmentInsulationMonitorThresholdService;

    @Override
    protected void saveHistoryData(CapacitanceEquipmentIm cacEntity, EquipmentInfoDto equipmentInfo) {
        // 设备状态
        String runState = iecBydworkParamService.getIecType(cacEntity.getMainTreeId(), cacEntity.getTimeStamp());
        if (StringUtils.isEmpty(runState)) {
            log.info("无法获取设备状态");
        }
        cacEntity.setRunState(runState);
        // 变压器还是避雷器
        cacEntity.setType(equipmentInfo.getType());
        //设置rowkey，导入hbase使用
        cacEntity.setHbaseRowkey(Tools.strReverse(TimeUtil.getTimeStr(cacEntity.getTimeStamp())) + "_"
            + cacEntity.getSensorId() + "_" + TimeUtil.getTimeStr(cacEntity.getTimeStamp()) + "_"
            + cacEntity.getCacMonitorTypeCode() + "_" + cacEntity.getMainTreeId());
        // 保存
        super.saveHistoryData(cacEntity, equipmentInfo);
    }

    @Override
    protected void saveBusiWarning(CapacitanceEquipmentIm cacEntity, String cacMonitorTypeCode, String sensorId,
        EquipmentInfoDto equipmentInfo) {
        // 阈值
        CapacitanceEquipmentInsulationMonitorThreshold arresterThreshold =
            capacitanceEquipmentInsulationMonitorThresholdService.getCapacitanceEquipmentInsulationMonitorThreshold(
                null, cacEntity.getRunState(), cacEntity.getSensorId());
        if (arresterThreshold == null) {
            log.info(
                "CapacitanceEquipmentInsulationMonitorThreshold not exists! mainTreeId: {}, runState: {}, sensorCode: {}",
                cacEntity.getMainTreeId(), cacEntity.getRunState(), cacEntity.getSensorId());
            return;
        }
        final StringBuilder warningMsg = new StringBuilder();

        // 泄漏电流、电容量、介质损耗因数的预警值、阈值
        String leakageCurrentThreshold = getThresholdVal(arresterThreshold, cacEntity.getPhase(), "LeakageCurrent");
        String capacitanceThreshold = getThresholdVal(arresterThreshold, cacEntity.getPhase(), "Capacitance");
        String lossFactorThreshold = getThresholdVal(arresterThreshold, cacEntity.getPhase(), "LossFactor");
        String leakageCurrentWarning = getWarningVal(arresterThreshold, cacEntity.getPhase(), "LeakageCurrent");
        String capacitanceWarning = getWarningVal(arresterThreshold, cacEntity.getPhase(), "Capacitance");
        String lossFactorWarning = getWarningVal(arresterThreshold, cacEntity.getPhase(), "LossFactor");

        String runState = cacEntity.getRunState();
        Map<String, Object> stabilityMap = busiStabilityService.getStabilityBySensorCodeAndStatus(sensorId, runState);

        // 泄漏电流
        BusiCapaItemVoBuilder builder1 = BusiCapaItemVo.builder().phase(cacEntity.getPhase()).name("泄漏电流（mA）")
            .collectValue(cacEntity.getTotalCurrent()).thresholdValue(leakageCurrentThreshold)
            .equipmentStatus(cacEntity.getRunState()).warningValue(leakageCurrentWarning);
        // 稳定性指标
        builder1.stabilityIndex(getString(stabilityMap, "leakageCurrent", "--"));
        if(isWarning(cacEntity.getTotalCurrent(),leakageCurrentWarning))
		{
        	append(warningMsg, format("{}泄漏电流超标为：{}", cacEntity.getPhase(), cacEntity.getTotalCurrent()));
            builder1.alarmValue(cacEntity.getTotalCurrent());
		}

        // 电容量
        BusiCapaItemVoBuilder builder2 = BusiCapaItemVo.builder().phase(cacEntity.getPhase()).name("电容（pF）")
            .collectValue(cacEntity.getCapacitance()).equipmentStatus(cacEntity.getRunState())
            .thresholdValue(capacitanceThreshold).warningValue(capacitanceWarning);
        // 稳定性指标
        builder2.stabilityIndex(getString(stabilityMap, "capacitance", "--"));
        if(isWarning(capacitanceThreshold,capacitanceWarning))
		{
        	append(warningMsg, format("{}电容量未达标为：{}", cacEntity.getPhase(), cacEntity.getCapacitance()));
            builder2.alarmValue(cacEntity.getCapacitance());
		}


        // 介质损耗因数
        BusiCapaItemVoBuilder builder3 = BusiCapaItemVo.builder().phase(cacEntity.getPhase()).name("介损（tgθ）")
            .collectValue(cacEntity.getLossFactor()).equipmentStatus(cacEntity.getRunState())
            .thresholdValue(lossFactorThreshold).warningValue(lossFactorWarning);
        // 稳定性指标
        builder3.stabilityIndex(getString(stabilityMap, "lossFactor", "--"));
        if(isWarning(cacEntity.getLossFactor(),lossFactorWarning))
		{
        	 append(warningMsg, format("{}介质损耗因数超标为：{}", cacEntity.getPhase(), cacEntity.getLossFactor()));
             builder3.alarmValue(cacEntity.getLossFactor());
		}
        //告警则保存告警
        if(warningMsg.length() > 0) {
        	  // 保存告警
            BusiEqmWarning busiEqmWarning = null;
            if (SiteTreeEnum.BYQ.getValue().equals(equipmentInfo.getType())) {
                busiEqmWarning = newEw(EqType.EQ_TYPE1, GzType.GZ_TYPE12, warningMsg.toString(), cacMonitorTypeCode,"1");
            } else if (SiteTreeEnum.BLQ.getValue().equals(equipmentInfo.getType())) {
                busiEqmWarning = newEw(EqType.EQ_TYPE3, GzType.GZ_TYPE12, warningMsg.toString(), cacMonitorTypeCode,"1");
            }
            if (busiEqmWarning == null) {
                log.warn("既不是变压器容性，也不是避雷器容性");
                return;
            }
            busiEqmWarning.setWarningTime(cacEntity.getTimeStamp());
            busiEqmWarning.setRunState(cacEntity.getRunState());
            busiEqmWarning.setWarningFlag("1");
            busiEqmWarning = this.buildWarning(busiEqmWarning, equipmentInfo);
            // 保存告警详情
            BusiCapaVo busiCapaVo = new BusiCapaVo();
            busiCapaVo.setEquipmentName(equipmentInfo.getSubEquipmentName());
            busiCapaVo.setList(Arrays.asList(builder1.build(),builder2.build(),builder3.build()));
            busiCapaVo.setCollectDate(cacEntity.getTimeStamp());
            this.buildWarningInfo(busiEqmWarning, JSON.toJSONString(busiCapaVo));
            return;
        }


        if(isThreshold(cacEntity.getTotalCurrent(),leakageCurrentThreshold,leakageCurrentWarning))
  		{
              append(warningMsg, format("{}泄漏电流超标为：{}", cacEntity.getPhase(), cacEntity.getTotalCurrent()));
              builder1.alarmValue(cacEntity.getTotalCurrent());
  		}
        if(isThreshold(cacEntity.getCapacitance(),capacitanceThreshold,capacitanceWarning))
  		{
        	  append(warningMsg, format("{}电容量未达标为：{}", cacEntity.getPhase(), cacEntity.getCapacitance()));
              builder2.alarmValue(cacEntity.getCapacitance());
  		}

        if(isThreshold(cacEntity.getLossFactor(), lossFactorThreshold,lossFactorWarning))
		{
        	append(warningMsg, format("{}介质损耗因数超标为：{}", cacEntity.getPhase(), cacEntity.getLossFactor()));
        	builder3.alarmValue(cacEntity.getLossFactor());
		}

        if(warningMsg.length() > 0)
        {
        	 // 保存告警
            BusiEqmWarning busiEqmWarning = null;
            if (SiteTreeEnum.BYQ.getValue().equals(equipmentInfo.getType())) {
                busiEqmWarning = newEw(EqType.EQ_TYPE1, GzType.GZ_TYPE12, warningMsg.toString(), cacMonitorTypeCode,"2");
            } else if (SiteTreeEnum.BLQ.getValue().equals(equipmentInfo.getType())) {
                busiEqmWarning = newEw(EqType.EQ_TYPE3, GzType.GZ_TYPE12, warningMsg.toString(), cacMonitorTypeCode,"2");
            }
            if (busiEqmWarning == null) {
                log.warn("既不是变压器容性，也不是避雷器容性");
                return;
            }
            busiEqmWarning.setWarningTime(cacEntity.getTimeStamp());
            busiEqmWarning.setRunState(cacEntity.getRunState());
            busiEqmWarning.setWarningFlag("1");
            busiEqmWarning = this.buildWarning(busiEqmWarning, equipmentInfo);
            // 保存告警详情
            BusiCapaVo busiCapaVo = new BusiCapaVo();
            busiCapaVo.setEquipmentName(equipmentInfo.getSubEquipmentName());
            busiCapaVo.setList(Arrays.asList(builder1.build(),builder2.build(),builder3.build()));
            busiCapaVo.setCollectDate(cacEntity.getTimeStamp());
            this.buildWarningInfo(busiEqmWarning, JSON.toJSONString(busiCapaVo));
            return;
        }
        if (warningMsg.length() == 0) {
            return;
        }
    }

    /**
     * 返回 aVal.compareTo(bVal)>0的结果，判断aVal是否大于bVal
     *
     * @param aVal  报文数据
     * @param bVal  阈值
     * @param cVal  预警值
     * @return  0,正常；1预警；2告警
     */
//    private static String gt(String aVal, String bVal,String cVal) {
//    	//return DecimalUtil.getVal(aVal).compareTo(DecimalUtil.getVal(bVal)) > 0;
//    	String flag = "0";
//
//    	if (StringUtils.isEmpty(bVal)) {
//    		return "0";
//    	}
//    	//预警
//    	if( DecimalUtil.getVal(aVal).compareTo(DecimalUtil.getVal(bVal)) > 0)
//    	{
//    		if( DecimalUtil.getVal(aVal).compareTo(DecimalUtil.getVal(cVal)) < 0)
//    		{
//    			flag = "2";
//    		}
//    	}
//    	//告警
//    	if(DecimalUtil.getVal(aVal).compareTo(DecimalUtil.getVal(cVal)) > 0)
//    	{
//    		flag = "1";
//    	}
//    	return flag;
//    }


    /**
     * 判断告警
     * 返回 aVal.compareTo(bVal)>0的结果，判断aVal是否大于bVal
     *
     * @param aVal  报文数据
     * @param bVal  阈值
     */
    private static boolean isWarning(String aVal, String bVal) {
        if (StringUtils.isEmpty(aVal)) {
            return false;
        }
    	if (StringUtils.isEmpty(bVal)) {
    		return false;
    	}
    	return DecimalUtil.getVal(aVal).compareTo(DecimalUtil.getVal(bVal)) > 0;
    }

    /**
     * 判断预警
     * 返回 aVal.compareTo(bVal)>0的结果，判断aVal是否大于bVal
     *
     * @param aVal  报文数据
     * @param bVal  阈值
     * @param cVal  预警值
     * @return  0,正常；1预警；2告警
     */
    private static boolean isThreshold(String aVal, String bVal,String cVal) {
    	boolean flag = false;
        if (StringUtils.isEmpty(aVal)) {
            return false;
        }
    	if (StringUtils.isEmpty(bVal)) {
    		return false;
    	}
    	//预警
    	if(DecimalUtil.getVal(aVal).compareTo(DecimalUtil.getVal(bVal)) > 0)
    	{
    		flag = true;
    	}
    	return flag;
    }


    private String getWarningVal(CapacitanceEquipmentInsulationMonitorThreshold threshold, String phase, String name) {
        return (String)FieldUtil.getFieldValue(threshold, phase(phase) + name + "Warning");
    }

    private String getThresholdVal(CapacitanceEquipmentInsulationMonitorThreshold threshold, String phase,
        String name) {
        return (String)FieldUtil.getFieldValue(threshold, phase(phase) + name + "Threshold");
    }

    private static String phase(String phase) {
        if (phase == null) {
            return "";
        }
        return phase.toLowerCase();
    }

    @Override
    protected void updateCurrentData(CapacitanceEquipmentIm cacEntity, EquipmentInfoDto equipmentInfo) {
        capacitanceEquipmentImCacheService.saveCapacitanceEquipmentImCache(cacEntity, equipmentInfo);
    }

    @Override
    public Map<String, Object> findCACPageData(Map<String, Object> params) {
        if (params.get("page") != null && params.get("limit") != null) {
            PageHelper.startPage(page(params), limit(params));
        }
        Page<Map<String, Object>> page = null;
        if (SiteTreeEnum.BYQ.getValue().equals(params.get("type").toString())) {
            page = capacitanceEquipmentImMapper.findTransformerCACPageData(params);
        } else {
            page = capacitanceEquipmentImMapper.findArresterCACPageData(params);
        }
        return ResultUtil.put(ConstantUtil.REQUEST_SUCCESS, page.getTotal(), "", page.getResult());
    }

    @Override
    public Map<String, Object> exportCacMonitorData(Map<String, Object> mapParams) {
        Map<String, Object> returnMap = new HashMap<>();
        if (mapParams.containsKey("mainTreeId") && StringUtils.isNotEmpty(mapParams.get("mainTreeId") + "")) {
            BusiSiteTree busiSiteTree = busiSiteTreeService.findByPK(mapParams.get("mainTreeId") + "");
            List<CapacitanceEquipmentImVo> capacitanceEquipmentImList = null;
            if (SiteTreeEnum.BYQ.getValue().equals(mapParams.get("type").toString())) {
                capacitanceEquipmentImList = capacitanceEquipmentImMapper.exportTransformerCacMonitorData(mapParams);
            } else {
                capacitanceEquipmentImList = capacitanceEquipmentImMapper.exportArresterCacMonitorData(mapParams);
            }
            String replaceRegex = "[\\\\n`~!@#$%^&*()+=|{}':;',\\\\\\\\[\\\\\\\\].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。， 、？]";
            String treeName = busiSiteTree.getName().replaceAll(replaceRegex, "-");
            returnMap.put("fileName", String.format("%s%s", treeName, "容性监测数据"));
            returnMap.put("title", String.format("%s%s", treeName, "容性监测数据"));
            if (capacitanceEquipmentImList.isEmpty()) {
                capacitanceEquipmentImList = new ArrayList<>();
                capacitanceEquipmentImList.add(new CapacitanceEquipmentImVo());
            }
            returnMap.put("data", capacitanceEquipmentImList);
        } else {
            throw new RuntimeException("主设备编码不正确");
        }
        return returnMap;
    }

    @Override
    protected List<Map<String, Object>> queryMonitorDataList(LocalDateTime startTime, LocalDateTime endTime) {
        return capacitanceEquipmentImMapper.queryMonitorDataList(startTime, endTime);
    }

    @Override
    protected void saveBusiOnlineMonitorData(BusiOnlineMonitorData busiOnlineMonitorData, Map<String, Object> item) {
        String type = popString(item, "type");
        if (SiteTreeEnum.BYQ.getValue().equals(type)) {
            busiOnlineMonitorData.setEquipmentType(SiteTreeEnum.BYQ_EQM.getValue());
            busiOnlineMonitorData.setSubEquipmentType(TransfromerTreeEnum.RX_EQM.getValue());
            busiOnlineMonitorData.setExtType(ExternalTypeEnum.BYQ.getValue());
        } else if (SiteTreeEnum.GIS.getValue().equals(type)) {
            throw new OwlException("GIS容性-绝缘监测未处理");
        } else if (SiteTreeEnum.CW.getValue().equals(type)) {
            throw new OwlException("测温容性-绝缘监测未处理");
        } else if (SiteTreeEnum.BLQ.getValue().equals(type)) {
            busiOnlineMonitorData.setEquipmentType(SiteTreeEnum.BLQ_HL_EQM.getValue());
            busiOnlineMonitorData.setSubEquipmentType(ArresterTreeEnum.RX_EQM.getValue());
            busiOnlineMonitorData.setExtType(ExternalTypeEnum.BLQ.getValue());
        } else if (SiteTreeEnum.OTHER.getValue().equals(type)) {
            throw new OwlException("其他容性-绝缘监测未处理");
        } else {
            throw new OwlException(
                format("数据错误，sensorCode: {}, type: {}", busiOnlineMonitorData.getSensorCode(), type));
        }
        // 这里将保存的任务交给父类方法完成，子类只需要修改指定几个字段就可以了
        super.saveBusiOnlineMonitorData(busiOnlineMonitorData, item);
    }

    @Override
    protected Map<String, Object> thresholdDataMap(BusiOnlineMonitorDataVo vo) {
        CapacitanceEquipmentInsulationMonitorThreshold thresholdVo =
            capacitanceEquipmentInsulationMonitorThresholdService.getCapacitanceEquipmentInsulationMonitorThreshold(
                vo.getMainTreeId(), vo.getRunState(), vo.getSensorCode());
        return Tools.beanToMap(thresholdVo, "id");
    }

    @Override
    public List<CapacitanceEquipmentImStabilityVo> getByStatus(String sensorCode, String status, LocalDateTime begin,
        LocalDateTime end) {
        return capacitanceEquipmentImMapper.selectByStatus(sensorCode, status, begin, end);
    }

    @Override
    public CapacitanceEquipmentImStatisticsVo getListEquInfo(String cacMonitorTypeCode, LocalDate day,
        String sensorCode) {
        CapacitanceEquipmentImStatisticsDto param = new CapacitanceEquipmentImStatisticsDto();
        param.setCacMonitorTypeCode(cacMonitorTypeCode);
        param.setStartTime(day.atStartOfDay());
        param.setEndTime(day.plusDays(1).atStartOfDay());
        param.setSensorCode(sensorCode);
        List<CapacitanceEquipmentImStatisticsVo> list = capacitanceEquipmentImMapper.getListEquInfo(param);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        return list.get(0);
    }

    // *****************************趋势图部分********************************\\
    @Override
    public List<BaseCurveQueryDto> findSensorCodeList(LocalDate day) {
        return capacitanceEquipmentImMapper.findSensorCodeList(day.atStartOfDay(), day.plusDays(1).atStartOfDay());
    }

    @Override
    public List<PointItemVo> findDaylyPointList(BaseCurveQueryDto sensorCode, LocalDate day, String subType) {
        return capacitanceEquipmentImMapper.findDaylyPointList(sensorCode, subType, day.atStartOfDay(),
            day.plusDays(1).atStartOfDay());
    }

    @Override
    public PointItemDto getDaylyPointStatistics(BaseCurveQueryDto param) {
        return capacitanceEquipmentImMapper.getDaylyPointStatistics(param);
    }
}
