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

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.google.common.collect.Maps;
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.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.EquipmentInfoDto;
import com.huatek.busi.dto.LightningrodImStatisticsDto;
import com.huatek.busi.dto.curve.BaseCurveQueryDto;
import com.huatek.busi.dto.curve.PointItemDto;
import com.huatek.busi.entity.ArresterInsulationMonitorThreshold;
import com.huatek.busi.entity.BusiEqmWarning;
import com.huatek.busi.entity.BusiOnlineMonitorData;
import com.huatek.busi.entity.BusiSiteTree;
import com.huatek.busi.entity.LightningrodIm;
import com.huatek.busi.entity.RptAretMonitor;
import com.huatek.busi.mapper.LightningrodImMapper;
import com.huatek.busi.mapper.RptAretMonitorMapper;
import com.huatek.busi.service.BusiSiteTreeService;
import com.huatek.busi.service.IecBydworkParamService;
import com.huatek.busi.service.arrester.LightningrodImService;
import com.huatek.busi.service.arrester.RptAretMonitorService;
import com.huatek.busi.service.impl.cac.AbstractCacEtlService;
import com.huatek.busi.service.threshold.ArresterInsulationMonitorThresholdService;
import com.huatek.busi.vo.LightningrodImStatisticsVo;
import com.huatek.busi.vo.LightningrodImVo;
import com.huatek.busi.vo.curve.PointItemVo;
import com.huatek.busi.vo.monitor.BusiOnlineMonitorDataVo;
import com.huatek.busi.vo.stability.LightningrodImStabilityVo;
import com.huatek.busi.vo.warning.BusiArresterItemVo;
import com.huatek.busi.vo.warning.BusiArresterItemVo.BusiArresterItemVoBuilder;
import com.huatek.busi.vo.warning.BusiArresterVo;
import com.huatek.busi.vo.warning.BusiGisSf6Vo;
import com.huatek.torch.frame.tools.ConstantUtil;
import com.huatek.torch.frame.tools.ResultUtil;

import lombok.extern.slf4j.Slf4j;

/**
 * 金属氧化物避雷器——绝缘监测：023001 ServiceImpl
 *
 * @author anker_cheng
 * @date Jun 26, 2019 1:11:48 PM
 */
@Slf4j
@Component
@Service(interfaceClass = LightningrodImService.class)
@Transactional(rollbackFor = Exception.class)
public class LightningrodImServiceImpl extends AbstractCacEtlService<LightningrodIm> implements LightningrodImService {

    @Autowired
    private LightningrodImMapper lightningrodImMapper;
    @Autowired
    private RptAretMonitorMapper rptAretMonitorMapper;

    @Reference(check = false)
    private RptAretMonitorService rptAretMonitorService;
    @Reference(check = false)
    private IecBydworkParamService iecBydworkParamService;
    
    @Reference(check = false)
    private BusiSiteTreeService busiSiteTreeService;
    
    @Reference(check = false)
    private ArresterInsulationMonitorThresholdService arresterInsulationMonitorThresholdService;

    @Override
    public void saveHistoryData(LightningrodIm cacEntity, EquipmentInfoDto equipmentInfo) {
        // 设备状态
        String state = iecBydworkParamService.getIecType(cacEntity.getMainTreeId(), cacEntity.getTimeStamp());
        if (StringUtils.isEmpty(state)) {
            log.info("无法获取设备状态");
        }
        cacEntity.setRunState(state);
        //设置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
    public void saveBusiWarning(LightningrodIm cacEntity, String cacMonitorTypeCode, String sensorId,
        EquipmentInfoDto equipmentInfo) {
        // 阈值
        ArresterInsulationMonitorThreshold arresterThreshold =
            arresterInsulationMonitorThresholdService.getArresterInsulationMonitorThreshold(cacEntity.getMainTreeId(),
                cacEntity.getRunState(), cacEntity.getSensorId());
        if (arresterThreshold == null) {
            log.warn("ArresterInsulationMonitorThreshold not exists! mainTreeId: {}, runState: {}, sensorCode: {}",
                cacEntity.getMainTreeId(), cacEntity.getRunState(), cacEntity.getSensorId());
            return;
        }
        final StringBuilder warningMsg = new StringBuilder();

        // 全电流、阻性电流的预警值、阈值
        String fullCurrentWarning = getWarningVal(arresterThreshold, cacEntity.getPhase(), "FullCurrent");
        String fullCurrentThreshold = getThresholdVal(arresterThreshold, cacEntity.getPhase(), "FullCurrent");
        String resistiveCurrentWarning = getWarningVal(arresterThreshold, cacEntity.getPhase(), "ResistiveCurrent");
        String resistiveCurrentThreshold = getThresholdVal(arresterThreshold, cacEntity.getPhase(), "ResistiveCurrent");

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

        // 全电流
        BusiArresterItemVoBuilder builder1 = BusiArresterItemVo.builder().phase(cacEntity.getPhase()).name("全电流（mA）")
            .collectValue(cacEntity.getTotalCurrent()).thresholdValue(fullCurrentThreshold)
            .equipmentStatus(cacEntity.getRunState()).warningValue(fullCurrentWarning);
        //数据稳定性
         builder1.stabilityIndex(getString(stabilityMap, "totalCurrent", "--"));
//        if (gt(cacEntity.getTotalCurrent(), arresterThreshold.getAFullCurrentThreshold(),arresterThreshold.getAFullCurrentWarning())) {
//            append(warningMsg, format("{}全电流超标为：{}", cacEntity.getPhase(), cacEntity.getTotalCurrent()));
//            builder1.alarmValue(cacEntity.getTotalCurrent());
//        }

        String fFullCurrent = gt(cacEntity.getTotalCurrent(), arresterThreshold.getAFullCurrentThreshold(),arresterThreshold.getAFullCurrentWarning());
        if("1".equals(fFullCurrent))
        {
        	append(warningMsg, format("{}全电流超标为：{}", cacEntity.getPhase(), cacEntity.getTotalCurrent()));
            builder1.alarmValue(cacEntity.getTotalCurrent());
            // 保存告警
            BusiEqmWarning busiEqmWarning = newEw(EqType.EQ_TYPE3, GzType.GZ_TYPE6, warningMsg.toString(), cacMonitorTypeCode,"1");
            busiEqmWarning.setWarningTime(cacEntity.getTimeStamp());
            busiEqmWarning.setRunState(cacEntity.getRunState());
            busiEqmWarning.setWarningFlag("1");
            busiEqmWarning = this.buildWarning(busiEqmWarning, equipmentInfo);
            // 保存告警详情
            BusiArresterVo busiArresterVo = new BusiArresterVo();
            busiArresterVo.setEquipmentName(equipmentInfo.getSubEquipmentName());
            busiArresterVo.setList(Arrays.asList(builder1.build()));
            busiArresterVo.setCollectDate(cacEntity.getTimeStamp());
            this.buildWarningInfo(busiEqmWarning, JSON.toJSONString(busiArresterVo));
        }else if("2".equals(fFullCurrent))  //预警
        {
        	append(warningMsg, format("{}全电流超标为：{}", cacEntity.getPhase(), cacEntity.getTotalCurrent()));
            builder1.alarmValue(cacEntity.getTotalCurrent());
            // 保存告警
            BusiEqmWarning busiEqmWarning = newEw(EqType.EQ_TYPE3, GzType.GZ_TYPE6, warningMsg.toString(), cacMonitorTypeCode,"2");
            busiEqmWarning.setWarningTime(cacEntity.getTimeStamp());
            busiEqmWarning.setRunState(cacEntity.getRunState());
            busiEqmWarning.setWarningFlag("2");
            busiEqmWarning = this.buildWarning(busiEqmWarning, equipmentInfo);
            // 保存告警详情
            BusiArresterVo busiArresterVo = new BusiArresterVo();
            busiArresterVo.setEquipmentName(equipmentInfo.getSubEquipmentName());
            busiArresterVo.setList(Arrays.asList(builder1.build()));
            busiArresterVo.setCollectDate(cacEntity.getTimeStamp());
            this.buildWarningInfo(busiEqmWarning, JSON.toJSONString(busiArresterVo));
        }
        
        
        // 阻性电流
        BusiArresterItemVoBuilder builder2 = BusiArresterItemVo.builder().phase(cacEntity.getPhase()).name("阻性电流（mA）")
            .collectValue(cacEntity.getResistiveCurrent()).thresholdValue(resistiveCurrentThreshold)
            .equipmentStatus(cacEntity.getRunState()).warningValue(resistiveCurrentWarning);
        //数据稳定性
        builder2.stabilityIndex(getString(stabilityMap, "resistiveCurrent", "--"));
//        if (gt(cacEntity.getResistiveCurrent(), arresterThreshold.getAResistiveCurrentThreshold(),arresterThreshold.getAResistiveCurrentWarning())) {
//            append(warningMsg, format("{}阻性电流超标为：{}", cacEntity.getPhase(), cacEntity.getResistiveCurrent()));
//            builder2.alarmValue(cacEntity.getResistiveCurrent());
//        }
        
       String aResistiveCurrent = gt(cacEntity.getResistiveCurrent(), arresterThreshold.getAResistiveCurrentThreshold(),arresterThreshold.getAResistiveCurrentWarning());

       if("1".equals(aResistiveCurrent))
       {
    	   append(warningMsg, format("{}阻性电流超标为：{}", cacEntity.getPhase(), cacEntity.getResistiveCurrent()));
           builder2.alarmValue(cacEntity.getResistiveCurrent());
           
           // 保存告警
           BusiEqmWarning busiEqmWarning = newEw(EqType.EQ_TYPE3, GzType.GZ_TYPE6, warningMsg.toString(), cacMonitorTypeCode,"1");
           busiEqmWarning.setWarningTime(cacEntity.getTimeStamp());
           busiEqmWarning.setRunState(cacEntity.getRunState());
           busiEqmWarning.setWarningFlag("1");
           busiEqmWarning = this.buildWarning(busiEqmWarning, equipmentInfo);
           // 保存告警详情
           BusiArresterVo busiArresterVo = new BusiArresterVo();
           busiArresterVo.setEquipmentName(equipmentInfo.getSubEquipmentName());
           busiArresterVo.setList(Arrays.asList(builder2.build()));
           busiArresterVo.setCollectDate(cacEntity.getTimeStamp());
           this.buildWarningInfo(busiEqmWarning, JSON.toJSONString(busiArresterVo));
           
       }else if("2".equals(aResistiveCurrent))  //预警
       {
    	   append(warningMsg, format("{}阻性电流超标为：{}", cacEntity.getPhase(), cacEntity.getResistiveCurrent()));
           builder2.alarmValue(cacEntity.getResistiveCurrent());
           
           // 保存告警
           BusiEqmWarning busiEqmWarning = newEw(EqType.EQ_TYPE3, GzType.GZ_TYPE6, warningMsg.toString(), cacMonitorTypeCode,"2");
           busiEqmWarning.setWarningTime(cacEntity.getTimeStamp());
           busiEqmWarning.setRunState(cacEntity.getRunState());
           busiEqmWarning.setWarningFlag("2");
           busiEqmWarning = this.buildWarning(busiEqmWarning, equipmentInfo);
           // 保存告警详情
           BusiArresterVo busiArresterVo = new BusiArresterVo();
           busiArresterVo.setEquipmentName(equipmentInfo.getSubEquipmentName());
           busiArresterVo.setList(Arrays.asList(builder2.build()));
           busiArresterVo.setCollectDate(cacEntity.getTimeStamp());
           this.buildWarningInfo(busiEqmWarning, JSON.toJSONString(busiArresterVo));
       }
        // 累计落雷次数
        RptAretMonitor rptAretMonitor = rptAretMonitorMapper.getRptAretMonitor(cacEntity.getSubTreeId());
        if (rptAretMonitor != null) {
            int totalActionCount = DecimalUtil.getVal(rptAretMonitor.getArresterCount())
                .add(DecimalUtil.getVal(cacEntity.getActionCount())).intValue();
            builder1.totalActionCount(String.valueOf(totalActionCount));
            builder2.totalActionCount(String.valueOf(totalActionCount));
        } else {
            builder1.totalActionCount("-");
            builder2.totalActionCount("-");
        }

        if (warningMsg.length() == 0) {
            return;
        }
       
    }

    @Override
    public void updateCurrentData(LightningrodIm cacEntity) {
        rptAretMonitorService.saveRptAretMonitor(cacEntity);
    }

    /**
     * 返回 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;
    }

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

    private String getThresholdVal(ArresterInsulationMonitorThreshold 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.replace("相", "").toLowerCase();
    }
	/**
	 * 数据输入-绝缘监测原始数据查询
	 */
    @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 = lightningrodImMapper.findCACPageData(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<LightningrodImVo> lightningrodImList = lightningrodImMapper.exportCacMonitorData(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 (lightningrodImList.isEmpty()) {
				lightningrodImList = new ArrayList<>();
				lightningrodImList.add(new LightningrodImVo());
			}
			returnMap.put("data", lightningrodImList);
		} else {
			throw new RuntimeException("主设备编码不正确");
		}
		return returnMap;
	}

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

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

    @Override
    protected void saveBusiOnlineMonitorData(BusiOnlineMonitorData busiOnlineMonitorData, Map<String, Object> item) {
        busiOnlineMonitorData.setSubEquipmentType(ArresterTreeEnum.JY_EQM.getValue());
        busiOnlineMonitorData.setExtType(ExternalTypeEnum.BLQ.getValue());
        busiOnlineMonitorData.setEquipmentType(SiteTreeEnum.BLQ_HL_EQM.getValue());
        // 这里将保存的任务交给父类方法完成，子类只需要修改指定几个字段就可以了
        super.saveBusiOnlineMonitorData(busiOnlineMonitorData, item);
    }

    @Override
    protected Map<String, Object> thresholdDataMap(BusiOnlineMonitorDataVo vo) {
        Map<String, Object> tMap = Maps.newLinkedHashMapWithExpectedSize(10);
        ArresterInsulationMonitorThreshold thresholdVo = arresterInsulationMonitorThresholdService
            .getArresterInsulationMonitorThreshold(vo.getMainTreeId(), vo.getRunState(), vo.getSensorCode());
        if(thresholdVo == null) {
            return tMap;
        }
        String phase = phase(vo.getPhase());
        if("A".equalsIgnoreCase(phase)) {
            tMap.put("totalCurrentWarning", thresholdVo.getAFullCurrentWarning());
            tMap.put("totalCurrentThreshold", thresholdVo.getAFullCurrentThreshold());
            tMap.put("resistiveCurrentWarning", thresholdVo.getAResistiveCurrentWarning());
            tMap.put("resistiveCurrentThreshold", thresholdVo.getAResistiveCurrentThreshold());
            tMap.put("capacitanceCurrentWarning", thresholdVo.getACapacitanceCurrentWarning());
            tMap.put("capacitanceCurrentThreshold", thresholdVo.getACapacitanceCurrentThreshold());
        }else if("B".equals(phase)) {
            tMap.put("totalCurrentWarning", thresholdVo.getBFullCurrentWarning());
            tMap.put("totalCurrentThreshold", thresholdVo.getBFullCurrentThreshold());
            tMap.put("resistiveCurrentWarning", thresholdVo.getBResistiveCurrentWarning());
            tMap.put("resistiveCurrentThreshold", thresholdVo.getBResistiveCurrentThreshold());
            tMap.put("capacitanceCurrentWarning", thresholdVo.getBCapacitanceCurrentWarning());
            tMap.put("capacitanceCurrentThreshold", thresholdVo.getBCapacitanceCurrentThreshold());
        }else if("C".equals(phase)) {
            tMap.put("totalCurrentWarning", thresholdVo.getCFullCurrentWarning());
            tMap.put("totalCurrentThreshold", thresholdVo.getCFullCurrentThreshold());
            tMap.put("resistiveCurrentWarning", thresholdVo.getCResistiveCurrentWarning());
            tMap.put("resistiveCurrentThreshold", thresholdVo.getCResistiveCurrentThreshold());
            tMap.put("capacitanceCurrentWarning", thresholdVo.getCCapacitanceCurrentWarning());
            tMap.put("capacitanceCurrentThreshold", thresholdVo.getCCapacitanceCurrentThreshold());
        }
        return tMap;
    }

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

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

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

    @Override
    public PointItemDto getDaylyPointStatistics(BaseCurveQueryDto param) {
        return lightningrodImMapper.getDaylyPointStatistics(param);
    }
    
    /**
     * 获取避雷器最近半年类落雷监测次数
     */
	@Override
	public String getSensorActionCount(String sensorCode, LocalDateTime startTime, LocalDateTime endTime) {
		// TODO Auto-generated method stub
		Map<String, Object> param = Maps.newLinkedHashMapWithExpectedSize(3);
        param.put("sensorCode", sensorCode);
        param.put("startTime", startTime);
        param.put("endTime", endTime);
        String actionCount = lightningrodImMapper.getActionCount(param);
        return actionCount;
	}
}