package com.zcxk.charge.web.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.zcxk.charge.api.dto.*;
import com.zcxk.charge.api.enums.PipeNetEnum;
import com.zcxk.charge.api.enums.SceneTypeEnum;
import com.zcxk.charge.api.vo.*;
import com.zcxk.charge.core.dao.OnlineMonitorMapper;
import com.zcxk.charge.core.entity.MonitorDataEntity;
import com.zcxk.charge.core.entity.MonitorDataValueEntity;
import com.zcxk.charge.web.common.Pagination;
import com.zcxk.charge.web.service.DeviceAttributeSpecsService;
import com.zcxk.charge.web.service.OnlineMonitorService;
import com.zcxk.charge.web.util.OrgInfoUtil;
import com.zcxk.core.oauth2.pojo.LoginUser;
import com.zcxk.core.oauth2.util.UserUtil;
import com.zcxk.core.utils.ByteArrayUtils;
import com.zcxk.core.utils.DateUtil;
import com.zcxk.core.utils.ZoniotIntegerUtils;
import com.zcxk.core.utils.util.RedisUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @description
 * @author  yjy
 * @data 2020-12-2
 */
@Service
public class OnlineMonitorImpl implements OnlineMonitorService {

    @Resource
    private OnlineMonitorMapper onlineMonitorMapper;

    @Autowired
    private DeviceAttributeSpecsService deviceAttributeSpecsService;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private OrgInfoUtil orgInfoUtil;

    @Autowired
    private MonitorDataReportServiceImpl monitorDataReportServiceImpl;

    @Override
    public List<AlarmDetailsVo> selectAlarmDetails(AlarmDetailsDto alarmDetailsDto) {
        LoginUser loginUser = UserUtil.getCurrentUser();
        alarmDetailsDto.setTenantId(loginUser.getTenantId());
        alarmDetailsDto.setProgramItems(loginUser.getProgramItemList());
        alarmDetailsDto.setUserType(loginUser.getType());
        //1是公司，2是公司及以下，3部门，4部门及以下，5自定义
        alarmDetailsDto.setPermissonType(loginUser.getPermissonType());
        return onlineMonitorMapper.selectAlarmDetails(alarmDetailsDto);
    }

    @Override
    public List<Map<String, Object>> selectAlarmCount(AlarmDetailsDto alarmDetailsDto){
        LoginUser loginUser = UserUtil.getCurrentUser();
        alarmDetailsDto.setTenantId(loginUser.getTenantId());
        alarmDetailsDto.setProgramItems(loginUser.getProgramItemList());
        alarmDetailsDto.setUserType(loginUser.getType());
        //1是公司，2是公司及以下，3部门，4部门及以下，5自定义
        alarmDetailsDto.setPermissonType(loginUser.getPermissonType());
        return onlineMonitorMapper.selectAlarmCount(alarmDetailsDto);
    }

    @Override
    public List<MonitorDataCollectVo> selectMapSuspension(MonitorDataCollectDto monitorDataCollectDto) {
        LoginUser loginUser = UserUtil.getCurrentUser();
        monitorDataCollectDto.setTenantId(loginUser.getTenantId());
        monitorDataCollectDto.setProgramItems(loginUser.getProgramItemList());
        monitorDataCollectDto.setUserType(loginUser.getType());
        //1是公司，2是公司及以下，3部门，4部门及以下，5自定义
        monitorDataCollectDto.setPermissonType(loginUser.getPermissonType());
        monitorDataCollectDto.setType(3);
        List<MonitorDataCollectVo> result = onlineMonitorMapper.selectMapSuspension(monitorDataCollectDto);
        if (!StringUtils.isEmpty(monitorDataCollectDto.getSceneTypeName())) {
            monitorDataCollectDto.setType(1);
            List<MonitorDataCollectVo> calculateRes = onlineMonitorMapper.selectSceneParam(monitorDataCollectDto);
            getCalMonitorData(result, calculateRes);
            // 按水量倒序排序 如果是水源按照取水量排序，其他按照供水量
            if(SceneTypeEnum.WATER_SOURCE.getMessage().equals(monitorDataCollectDto.getSceneTypeName())){
                result.sort(Comparator.comparing(MonitorDataCollectVo::getIntakeWaterUsage,Comparator.nullsFirst(Double::compareTo)).reversed());
            }else{
                result.sort(Comparator.comparing(MonitorDataCollectVo::getYieldWaterUsage,Comparator.nullsFirst(Double::compareTo)).reversed());
            }
        }else{
            getCalMonitorData(result, new ArrayList<>());
        }
        return result;
    }

    @Override
    public List<MonitorDataCollectVo> selectMapSuspensionForMonth(MonitorDataCollectDto monitorDataCollectDto) {
        LoginUser loginUser = UserUtil.getCurrentUser();
        monitorDataCollectDto.setTenantId(loginUser.getTenantId());
        monitorDataCollectDto.setProgramItems(loginUser.getProgramItemList());
        monitorDataCollectDto.setUserType(loginUser.getType());
        //1是公司，2是公司及以下，3部门，4部门及以下，5自定义
        monitorDataCollectDto.setPermissonType(loginUser.getPermissonType());
        monitorDataCollectDto.setType(3);
        List<MonitorDataCollectVo> result = onlineMonitorMapper.selectSceneParamForLastMonth(monitorDataCollectDto);
        for(MonitorDataCollectVo mon:result){
            BigDecimal yieldWaterUsage=monitorDataReportServiceImpl.getAmountCount(null,mon.getSceneId().intValue(),"泵站",3,2);
            mon.setYieldWaterUsage(yieldWaterUsage.doubleValue());
        }
        result.sort(Comparator.comparing(MonitorDataCollectVo::getYieldWaterUsage,Comparator.nullsFirst(Double::compareTo)).reversed());
        return result;
    }

    @Override
    public List<MonitorDataCollectVo> selectMapParam(MonitorDataCollectDto monitorDataCollectDto)
    {
        LoginUser loginUser = UserUtil.getCurrentUser();
        monitorDataCollectDto.setTenantId(loginUser.getTenantId());
        monitorDataCollectDto.setProgramItems(loginUser.getProgramItemList());
        monitorDataCollectDto.setUserType(loginUser.getType());
        //1是公司，2是公司及以下，3部门，4部门及以下，5自定义
        monitorDataCollectDto.setPermissonType(loginUser.getPermissonType());
        monitorDataCollectDto.setType(4);
        List<MonitorDataCollectVo> result=onlineMonitorMapper.selectMapParam(monitorDataCollectDto);
        monitorDataCollectDto.setType(1);
        List<MonitorDataCollectVo> calculateRes=onlineMonitorMapper.selectSceneParam(monitorDataCollectDto);

        getCalMonitorData(result,calculateRes);
        return result;
    }

    @Override
    public IPage<OnlineDataVo> selectPage(IPage<OnlineDataDto> page, OnlineDataDto onlineDataDto) {
        LoginUser loginUser = UserUtil.getCurrentUser();
        onlineDataDto.setTenantId(loginUser.getTenantId());
        onlineDataDto.setProgramItems(loginUser.getProgramItemList());
        onlineDataDto.setUserType(loginUser.getType());
        //1是公司，2是公司及以下，3部门，4部门及以下，5自定义
        onlineDataDto.setPermissonType(loginUser.getPermissonType());

        IPage<OnlineDataVo> iPage = onlineMonitorMapper.selectPage(page,onlineDataDto);
        Pagination<OnlineDataVo> pages = new Pagination<>(iPage);
        MonitorDataCollectDto monitorDataCollectDto=new MonitorDataCollectDto();
        List<Long> sceneIds = pages.getList().stream().map(OnlineDataVo::getSceneId).collect(Collectors.toList());
        monitorDataCollectDto.setType(2);
        monitorDataCollectDto.setSceneIds(sceneIds);
        monitorDataCollectDto.setTenantId(loginUser.getTenantId());
        List<MonitorDataCollectVo> calculateRes=onlineMonitorMapper.selectSceneParam(monitorDataCollectDto);
        // 获取在线数据及计算数据
        getCalOnlineData(pages.getList(),calculateRes);
        return iPage;
    }

    @Override
    public List<Map<String, Object>> selectAlarmStats(AlarmDetailsDto alarmDetailsDto) {
        LoginUser loginUser = UserUtil.getCurrentUser();
        alarmDetailsDto.setTenantId(loginUser.getTenantId());
        alarmDetailsDto.setProgramItems(loginUser.getProgramItemList());
        alarmDetailsDto.setUserType(loginUser.getType());
        //1是公司，2是公司及以下，3部门，4部门及以下，5自定义
        alarmDetailsDto.setPermissonType(loginUser.getPermissonType());
        return onlineMonitorMapper.selectAlarmStats(alarmDetailsDto);
    }

    @Override
    public List<MonitorDataCollectVo> selectSceneParam(MonitorDataCollectDto monitorDataCollectDto){
        LoginUser loginUser = UserUtil.getCurrentUser();
        monitorDataCollectDto.setTenantId(loginUser.getTenantId());
        monitorDataCollectDto.setProgramItems(loginUser.getProgramItemList());
        monitorDataCollectDto.setUserType(loginUser.getType());
        //1是公司，2是公司及以下，3部门，4部门及以下，5自定义
        monitorDataCollectDto.setPermissonType(loginUser.getPermissonType());
        return onlineMonitorMapper.selectSceneParam(monitorDataCollectDto);
    }

    @Override
    public List<Map<String, Object>> selectDeviceCount(OnlineDataDto onlineDataDto) {
        LoginUser loginUser = UserUtil.getCurrentUser();
        onlineDataDto.setTenantId(loginUser.getTenantId());
        onlineDataDto.setProgramItems(loginUser.getProgramItemList());
        onlineDataDto.setUserType(loginUser.getType());
        //1是公司，2是公司及以下，3部门，4部门及以下，5自定义
        onlineDataDto.setPermissonType(loginUser.getPermissonType());
        return onlineMonitorMapper.selectDeviceCount(onlineDataDto);
    }

    @Override
    public List<MonitorDataCollectVo> selectDeviceMapParam(MonitorDataCollectDto monitorDataCollectDto)
    {
        LoginUser loginUser = UserUtil.getCurrentUser();
        monitorDataCollectDto.setTenantId(loginUser.getTenantId());
        monitorDataCollectDto.setProgramItems(loginUser.getProgramItemList());
        monitorDataCollectDto.setUserType(loginUser.getType());
        //1是公司，2是公司及以下，3部门，4部门及以下，5自定义
        monitorDataCollectDto.setPermissonType(loginUser.getPermissonType());
        List<MonitorDataCollectVo> result=onlineMonitorMapper.selectDeviceMapParam(monitorDataCollectDto);
        getCalMonitorData(result,new ArrayList<MonitorDataCollectVo>());
        return result;
    }


    @Override
    public List<DeviceCountStatsVo> statsDeviceQualified(OnlineDataDto onlineDataDto) {
        LoginUser loginUser = UserUtil.getCurrentUser();
        onlineDataDto.setTenantId(loginUser.getTenantId());
        onlineDataDto.setProgramItems(loginUser.getProgramItemList());
        onlineDataDto.setUserType(loginUser.getType());
        //1是公司，2是公司及以下，3部门，4部门及以下，5自定义
        onlineDataDto.setPermissonType(loginUser.getPermissonType());
        List<DeviceCountStatsVo> result=onlineMonitorMapper.statsDeviceQualified(onlineDataDto);
        if(!StringUtils.isEmpty(onlineDataDto.getSceneTypeName())&&result.size()>0&&onlineDataDto.getFlag()==null) {
            List<DeviceCountStatsVo> parmResult=onlineMonitorMapper.statsParmQualified(onlineDataDto);
            result.get(0).setParmQualified(parmResult);
            for(DeviceCountStatsVo parm : result.get(0).getParmQualified()){
                parm.setTotalCount(result.get(0).getTotalCount());
                parm.setNormalCount(result.get(0).getTotalCount()-parm.getAlarmCount());
            }
        }
        return result;
    }

    @Override
    public List<MonitorDataCollectVo> statsDeviceFlow(OnlineDataDto onlineDataDto)
    {
        LoginUser loginUser = UserUtil.getCurrentUser();
        onlineDataDto.setTenantId(loginUser.getTenantId());
        onlineDataDto.setProgramItems(loginUser.getProgramItemList());
        onlineDataDto.setUserType(loginUser.getType());
        //1是公司，2是公司及以下，3部门，4部门及以下，5自定义
        onlineDataDto.setPermissonType(loginUser.getPermissonType());

        List<MonitorDataCollectVo> result=onlineMonitorMapper.statsDeviceParm(onlineDataDto);
        getCalMonitorData(result,result);
        //去掉没有数据的值
        result.removeIf(r->r.getYieldWaterUsage() == null);
        //按水量倒序排序
        result.sort(new Comparator<MonitorDataCollectVo>() {
            @Override
            public int compare(MonitorDataCollectVo o1, MonitorDataCollectVo o2) {
                if(o1.getYieldWaterUsage()!=null&&o2.getYieldWaterUsage()!=null&&
                        o1.getYieldWaterUsage()>o2.getYieldWaterUsage()){
                    return -1;
                }
                return 0;
            }
        });
        return result;
    }

    @Override
    public DistributeIntervalDto statsDeviceParmCount(OnlineDataDto onlineDataDto){
        int[] deviceCount = new int[5];
        int count = 0;
        Double sumValue = null, maxValue = null, minValue = null;
        String maxDeviceName = null, minDeviceName = null;
        LoginUser loginUser = UserUtil.getCurrentUser();
        onlineDataDto.setTenantId(loginUser.getTenantId());
        onlineDataDto.setProgramItems(loginUser.getProgramItemList());
        onlineDataDto.setUserType(loginUser.getType());
        //1是公司，2是公司及以下，3部门，4部门及以下，5自定义
        onlineDataDto.setPermissonType(loginUser.getPermissonType());
        List<MonitorDataCollectVo> result = onlineMonitorMapper.statsDeviceParm(onlineDataDto);
        for (MonitorDataCollectVo monDataCol :result) {
            //取缓存里的数据
            byte[] bytes = redisUtil.get(("sms_water_" + monDataCol.getDeviceCode()).getBytes());
            MonitorDataEntity monitorDataEntity = null;
            if (bytes != null && bytes.length > 0) {
                monitorDataEntity = (MonitorDataEntity) ByteArrayUtils.bytesToObject(bytes).get();
            }
            if (monitorDataEntity == null) {
                continue;
            }
            for (MonitorDataVo monitorData : monDataCol.getMonitorDataEntities()) {
                monDataCol.setCollectDate(monitorDataEntity.getCollectDate());
                // 筛选该设备相同属性的值
                List<MonitorDataValueEntity> attributeEntities = monitorDataEntity.getDataValues().stream().filter((MonitorDataValueEntity m)
                        -> m.getAttributeId().equals(monitorData.getAttributeId())).collect(Collectors.toList());
                MonitorDataValueEntity attributeEntity = attributeEntities.size() > 0 ? attributeEntities.get(0) : null;
                if (attributeEntity != null) {
                    Double dataValue = attributeEntity.getDataValue();
                    if (dataValue != null){
                        if (PipeNetEnum.PRESSURE.getMessage().equals(onlineDataDto.getSceneTypeName())){
                            count++;
                            sumValue=sumValue==null?dataValue:sumValue+dataValue;
                            boolean isMaxEquals=dataValue.equals(maxValue);
                            boolean isMinEquals=dataValue.equals(minValue);
                            if (isMaxEquals) {
                                maxDeviceName += ","+monDataCol.getDeviceName();
                            }
                            if (isMinEquals) {
                                minDeviceName += ","+monDataCol.getDeviceName();
                            }
                            maxValue = Math.max(maxValue==null?dataValue:maxValue,dataValue);
                            minValue = Math.min(minValue==null?dataValue:minValue,dataValue);
                            if (maxValue.equals(dataValue)&&!isMaxEquals) {
                                maxDeviceName = monDataCol.getDeviceName();
                            }
                            if (minValue.equals(dataValue)&&!isMinEquals) {
                                minDeviceName = monDataCol.getDeviceName();
                            }
                            if(dataValue<=0.2){
                                deviceCount[0]++;
                            }else if(dataValue<=0.25) {
                                deviceCount[1]++;
                            }else if(dataValue<=0.3) {
                                deviceCount[2]++;
                            }else if(dataValue<=0.35) {
                                deviceCount[3]++;
                            }else if(dataValue>0.35) {
                                deviceCount[4]++;
                            }
                        }else if(PipeNetEnum.FLOW.getMessage().equals(onlineDataDto.getSceneTypeName())){
                            if(dataValue<=0){
                                deviceCount[0]++;
                            }else if(dataValue<=200) {
                                deviceCount[1]++;
                            }else if(dataValue<=400) {
                                deviceCount[2]++;
                            }else if(dataValue<=600) {
                                deviceCount[3]++;
                            }else if(dataValue>600) {
                                deviceCount[4]++;
                            }
                        }
                    }
                }
            }
        }
        deviceCount[0]=result.size()-deviceCount[1]-deviceCount[2]-deviceCount[3]-deviceCount[4];
        DistributeIntervalDto distributeIntervalDto=new DistributeIntervalDto();
        distributeIntervalDto.setDistributeValue(deviceCount);
        distributeIntervalDto.setAvgValue(count==0?null:sumValue/count);
        distributeIntervalDto.setMaxValue(maxValue);
        distributeIntervalDto.setMinValue(minValue);
        distributeIntervalDto.setMaxDeviceName(maxDeviceName);
        distributeIntervalDto.setMinDeviceName(minDeviceName);
        return distributeIntervalDto;
    }

    /**
     * 管网分页查询
     * @return
     */
    @Override
    public IPage<OnlineDataVo> selectPipeNetPage(IPage<OnlineDataDto> page, OnlineDataDto onlineDataDto) {
        LoginUser loginUser = UserUtil.getCurrentUser();
        onlineDataDto.setTenantId(loginUser.getTenantId());
        onlineDataDto.setProgramItems(loginUser.getProgramItemList());
        onlineDataDto.setUserType(loginUser.getType());
        //1是公司，2是公司及以下，3部门，4部门及以下，5自定义
        onlineDataDto.setPermissonType(loginUser.getPermissonType());

        IPage<OnlineDataVo> iPage =onlineMonitorMapper.selectPipeNetPage(page,onlineDataDto);
        Pagination<OnlineDataVo> pages = new Pagination<>(iPage);

        List<Long> deviceIds = pages.getList().stream().map(OnlineDataVo::getDeviceId).collect(Collectors.toList());
        onlineDataDto.setDeviceIds(deviceIds);
        onlineDataDto.setTenantId(loginUser.getTenantId());
        List<MonitorDataCollectVo> calculateRes=onlineMonitorMapper.statsDeviceParm(onlineDataDto);
        // 获取在线数据及计算数据
        getCalOnlineData(pages.getList(),calculateRes);
        return iPage;
    }
    /**
     * 查询管网地图图层
     * @return
     */
    @Override
    public  List<PipeNetLayerVo> selectPipeNetLayer(OnlineDataDto onlineDataDto)
    {
        LoginUser loginUser = UserUtil.getCurrentUser();
        onlineDataDto.setTenantId(loginUser.getTenantId());
        onlineDataDto.setProgramItems(loginUser.getProgramItemList());
        onlineDataDto.setUserType(loginUser.getType());
        //1是公司，2是公司及以下，3部门，4部门及以下，5自定义
        onlineDataDto.setPermissonType(loginUser.getPermissonType());
        List<PipeNetLayerVo> result=onlineMonitorMapper.selectPipeNetLayer(onlineDataDto);
        for(PipeNetLayerVo pipeNetLayerDto :result){
            getCalMonitorData(pipeNetLayerDto.getDeviceDataList(), new ArrayList<>());
        }
        return result;
    }

    /**
     * 统计从水源地到水龙头汇总数据
     * @return
     */
    @Override
    public DispatchSummaryDto statsDispatchSummary(MonitorDataCollectDto monitorDataCollectDto)
    {
        LoginUser loginUser = UserUtil.getCurrentUser();
        monitorDataCollectDto.setTenantId(loginUser.getTenantId());
        monitorDataCollectDto.setProgramItems(loginUser.getProgramItemList());
        monitorDataCollectDto.setUserType(loginUser.getType());
        //1是公司，2是公司及以下，3部门，4部门及以下，5自定义
        monitorDataCollectDto.setPermissonType(loginUser.getPermissonType());
        monitorDataCollectDto.setType(1);
        DispatchSummaryDto result=new DispatchSummaryDto();

        monitorDataCollectDto.setSceneTypeName("水源");
        List<MonitorDataCollectVo> waterHead=onlineMonitorMapper.selectSceneParam(monitorDataCollectDto);
        MonitorDataCollectDto waterHeadRes= getCalTotalData(waterHead);
        result.setIntakeWaterUsage(waterHeadRes.getIntakeWaterUsage());

        monitorDataCollectDto.setSceneTypeName("水厂");
        List<MonitorDataCollectVo> waterWorks=onlineMonitorMapper.selectSceneParam(monitorDataCollectDto);
        MonitorDataCollectDto waterWorksRes= getCalTotalData(waterWorks);
        result.setYieldWaterUsage(waterWorksRes.getYieldWaterUsage());
        result.setPowerUsage(waterWorksRes.getPowerUsage());

        Double invName=onlineMonitorMapper.selectTotalYieldWater(monitorDataCollectDto);
        result.setInvNameRate(invName!=null&&waterWorksRes.getYieldWaterUsage()!=null?waterWorksRes.getYieldWaterUsage()/invName*100:null);

        OnlineDataDto onlineDataDto=new OnlineDataDto();
        onlineDataDto.setSceneTypeName("压力");
        onlineDataDto.setSceneIds(monitorDataCollectDto.getSceneIds());
        List<DeviceCountStatsVo> pres=statsDeviceQualified(onlineDataDto);
        result.setPresQualifiedRate(pres.size()>0&&pres.get(0).getTotalCount()!=0&&pres.get(0).getParmQualified().size()>0?
                (double)pres.get(0).getParmQualified().get(0).getNormalCount()/pres.get(0).getTotalCount()*100:100);

        onlineDataDto.setSceneTypeName("水质");
        List<DeviceCountStatsVo> water=statsDeviceQualified(onlineDataDto);
        result.setWaterQualifiedRate(water.size()>0&&water.get(0).getTotalCount()!=0?(double)water.get(0).getNormalCount()/water.get(0).getTotalCount()*100:100);

        //售水量造假 产销差率30%~40%
        if(result.getYieldWaterUsage()!=null){
            result.setNrwRate(Math.random()*10+30);
            result.setSellWaterUsage((1-result.getNrwRate()/100)*result.getYieldWaterUsage());
        }
        return result;
    }

    @Override
    public List<SecDataCollectDto> selectMapForWholeCompany(MonitorDataCollectDto monitorDataCollectDto) {
        LoginUser loginUser = UserUtil.getCurrentUser();
        monitorDataCollectDto.setTenantId(loginUser.getTenantId());
        monitorDataCollectDto.setProgramItems(loginUser.getProgramItemList());
        monitorDataCollectDto.setUserType(loginUser.getType());
        //1是公司，2是公司及以下，3部门，4部门及以下，5自定义
        monitorDataCollectDto.setPermissonType(loginUser.getPermissonType());
        monitorDataCollectDto.setType(3);
        List<MonitorDataCollectVo> result=onlineMonitorMapper.selectMapSuspension(monitorDataCollectDto);
        List<SecDataCollectDto> secDataCollectDtos = new ArrayList<>();
        if(!StringUtils.isEmpty(monitorDataCollectDto.getSceneTypeName()))
        {
            Map<Long,SecDataCollectDto> map = new HashMap<>();
            // 按公司进行汇总
            for(MonitorDataCollectVo item : result) {
                System.out.println("公司ID:"+item.getCompanyOrgId());
                if (!map.containsKey(item.getCompanyOrgId())) {
                    SecDataCollectDto secDataCollectDto = new SecDataCollectDto();
                    secDataCollectDto.setCount(1);
                    secDataCollectDto.setComName(orgInfoUtil.getOrgName(item.getCompanyOrgId().intValue()));
                    BigDecimal yieldWaterUsage=monitorDataReportServiceImpl.getAmountCount(item.getCompanyOrgId().intValue(),null,"泵站",3,2);
                    secDataCollectDto.setYieldWaterUsage(yieldWaterUsage.doubleValue());
                    map.put(item.getCompanyOrgId(), secDataCollectDto);
                } else {
                    Integer count = map.get(item.getCompanyOrgId()).getCount() != null ? map.get(item.getCompanyOrgId()).getCount() : 1;
                    map.get(item.getCompanyOrgId()).setCount(count + 1);
                }
            }
            for (SecDataCollectDto value : map.values()) {
                secDataCollectDtos.add(value);
            }
            // 按水量倒序排序 如果是水源按照取水量排序，其他按照供水量
            secDataCollectDtos.sort(Comparator.comparing(SecDataCollectDto::getYieldWaterUsage,Comparator.nullsFirst(Double::compareTo)).reversed());
        }
        return secDataCollectDtos;
    }
    /**
     * 查询场景列表
     * @return
     */
    @Override
    public List<OnlineDataVo> selectList(OnlineDataDto onlineDataDto){
        LoginUser loginUser = UserUtil.getCurrentUser();
        onlineDataDto.setTenantId(loginUser.getTenantId());
        onlineDataDto.setProgramItems(loginUser.getProgramItemList());
        onlineDataDto.setUserType(loginUser.getType());
        //1是公司，2是公司及以下，3部门，4部门及以下，5自定义
        onlineDataDto.setPermissonType(loginUser.getPermissonType());

        List<OnlineDataVo> result =onlineMonitorMapper.selectList(onlineDataDto);
        MonitorDataCollectDto monitorDataCollectDto=new MonitorDataCollectDto();
        List<Long> sceneIds = result.stream().map(OnlineDataVo::getSceneId).collect(Collectors.toList());
        monitorDataCollectDto.setType(5);
        monitorDataCollectDto.setSceneIds(sceneIds);
        monitorDataCollectDto.setTenantId(loginUser.getTenantId());
        List<MonitorDataCollectVo> calculateRes=onlineMonitorMapper.selectSceneParam(monitorDataCollectDto);
        //获取在线数据及计算数据
        getCalOnlineData(result,calculateRes);
        return result;
    }
    /**
     * 查询管网设备列表
     * @return
     */
    @Override
    public List<OnlineDataVo> selectPipeNetList(OnlineDataDto onlineDataDto){
        LoginUser loginUser = UserUtil.getCurrentUser();
        onlineDataDto.setTenantId(loginUser.getTenantId());
        onlineDataDto.setProgramItems(loginUser.getProgramItemList());
        onlineDataDto.setUserType(loginUser.getType());
        //1是公司，2是公司及以下，3部门，4部门及以下，5自定义
        onlineDataDto.setPermissonType(loginUser.getPermissonType());

        List<OnlineDataVo> result =onlineMonitorMapper.selectPipeNetList(onlineDataDto);
        List<Long> deviceIds = result.stream().map(OnlineDataVo::getDeviceId).collect(Collectors.toList());
        onlineDataDto.setDeviceIds(deviceIds);
        onlineDataDto.setTenantId(loginUser.getTenantId());
        List<MonitorDataCollectVo> calculateRes=onlineMonitorMapper.statsDeviceParm(onlineDataDto);
        // 获取在线数据及计算数据
        getCalOnlineData(result,calculateRes);
        return result;
    }

    private MonitorDataEntity getCacheData(String key){
        byte[] bytes = redisUtil.get(("sms_water_" + key)).getBytes();
        if (bytes == null || bytes.length == 0){
            return null;
        }
        return (MonitorDataEntity)ByteArrayUtils.bytesToObject(bytes).get();
    }



    /**
    * 获取在线数据及计算数据
    * @author Andy
    * @date 15:49 2021/8/18
    * @param result:
    * @param calculateRes:
    * @return void
    **/
    public void getCalMonitorData(List<MonitorDataCollectVo> result,List<MonitorDataCollectVo> calculateRes){
        for (MonitorDataCollectVo monDataCol : result) {
            MonitorDataEntity monitorDataEntity = null;
            if (monDataCol.getDeviceId() != null) {
                monitorDataEntity = getCacheData(monDataCol.getDeviceCode());
            }
            // 获取最新数据 更新
            for(MonitorDataVo monData : monDataCol.getMonitorDataEntities()) {
                if (monDataCol.getDeviceId() == null) {
                   monitorDataEntity = getCacheData(monData.getDeviceCode());
                }
                if (monitorDataEntity != null) {
                    if (monDataCol.getCollectDate() ==null || monitorDataEntity.getCollectDate().getTime()>monDataCol.getCollectDate().getTime() ){
                        monDataCol.setCollectDate(monitorDataEntity.getCollectDate());
                    }
                    // 筛选该设备相同属性的值
                    MonitorDataValueEntity  attributeEntity = getMonitorDataValueEntity(monitorDataEntity, monData);
                    if (attributeEntity != null) {
                        // 赋值
                        monData.setDataValue(attributeEntity.getDataValue());
                        // 如果是状态值 需转换
                        if ("1".equals(monData.getAttributeType()) || "2".equals(monData.getAttributeType())) {
                            // 去掉末尾小数点
                            DecimalFormat decimalFormat = new DecimalFormat("###################.###########");
                            String specsValue = attributeEntity.getDataValue() == null ? null : decimalFormat.format(attributeEntity.getDataValue());
                            monData.setSpecsName(specsValue == null ? null : deviceAttributeSpecsService.selectSpecsName(attributeEntity.getAttributeId(), specsValue));
                        }
                    }
                }
            }
            // 计算数据 更新
            for (MonitorDataCollectVo calculate :calculateRes ) {
                //相同场景或设备 则取值计算
                if (ZoniotIntegerUtils.equal(monDataCol.getDeviceId(),calculate.getSceneId()) ||
                        ZoniotIntegerUtils.equal(monDataCol.getDeviceId(),calculate.getDeviceId())) {
                    for (MonitorDataVo monitorData : calculate.getMonitorDataEntities()){
                        if (monDataCol.getDeviceId() == null) {
                             monitorDataEntity = getCacheData(monitorData.getDeviceCode());
                        }
                        if (monitorDataEntity == null) {
                            continue;
                        }
                        // 日期算换格式
                        SimpleDateFormat formatdate = new SimpleDateFormat("yyyy-MM-dd");
                        // 计算今日数据
                        if (formatdate.format(new Date()).equals(formatdate.format(monitorDataEntity.getCollectDate()))) {
                            // 筛选该设备相同属性的值
                            MonitorDataValueEntity  attributeEntity = getMonitorDataValueEntity(monitorDataEntity, monitorData);
                            if (attributeEntity != null) {
                                Double attributeValue = 0d;
                                if(attributeEntity.getDataValue() != null && monitorData.getLatestValue() != null){
                                    attributeValue = attributeEntity.getDataValue() - monitorData.getLatestValue();
                                }
                                setMonitorDataCollectVo(monitorData.getAttributeType(), monDataCol, attributeValue);
                            }
                        }
                    }
                }
            }
        }
        for(MonitorDataCollectVo mon : result){
            if (SceneTypeEnum.WATER_SOURCE.getMessage().equals(mon.getSceneTypeName())
                    || SceneTypeEnum.WATER_WORKS.getMessage().equals(mon.getSceneTypeName())){
                if(mon.getYieldWaterUsage()!=null) {
                    mon.setYieldWaterUsage(mon.getYieldWaterUsage() / 10000);
                }
                if(mon.getIntakeWaterUsage()!=null) {
                    mon.setIntakeWaterUsage(mon.getIntakeWaterUsage() / 10000);
                }
                if(mon.getPowerUsage()!=null) {
                    mon.setPowerUsage(mon.getPowerUsage() / 10000);
                }
            }
        }
    }

    /**
     * 筛选该设备相同属性的值
     * @author Andy
     * @date 16:11 2021/8/18
     * @param monitorDataEntity:
     * @param monData:
     * @return com.zcxk.charge.core.entity.MonitorDataValueEntity
     **/
    private MonitorDataValueEntity getMonitorDataValueEntity(MonitorDataEntity monitorDataEntity, MonitorDataVo monData){
        List<MonitorDataValueEntity>  attributeEntities = monitorDataEntity.getDataValues().stream().filter((MonitorDataValueEntity m)
                ->m.getAttributeId().equals(monData.getAttributeId())).collect(Collectors.toList());
        return attributeEntities.size() > 0 ? attributeEntities.get(0) : null;
    }

    /**
     * 获取在线数据及计算数据
     */
    public void getCalOnlineData(List<OnlineDataVo> result,List<MonitorDataCollectVo> calculateRes){
        for(MonitorDataCollectVo calculate :calculateRes ) {
            MonitorDataEntity monitorDataEntity =null;
            if (calculate.getDeviceId()!=null) {
                monitorDataEntity = getCacheData(calculate.getDeviceCode());
            }
            for(OnlineDataVo monDataCol : result) {
                // 相同场景或设备 则取值计算
                if (ZoniotIntegerUtils.equal(monDataCol.getSceneId(),calculate.getSceneId()) ||
                        ZoniotIntegerUtils.equal(monDataCol.getDeviceId(),calculate.getDeviceId())) {
                    // 水泵状态
                    List<MonitorDataVo> pumpStatus = new ArrayList<>(0);
                    for (MonitorDataVo monitorData : calculate.getMonitorDataEntities()){
                        if (monDataCol.getDeviceId() == null) {
                             monitorDataEntity = getCacheData(monitorData.getDeviceCode());
                        }
                        if (monitorDataEntity != null) {
                            if (monDataCol.getCollectDate()==null || monitorDataEntity.getCollectDate().getTime() > monDataCol.getCollectDate().getTime()){
                                monDataCol.setCollectDate(monitorDataEntity.getCollectDate());
                            }
                            // 筛选该设备相同属性的值
                            List<MonitorDataValueEntity> attributeEntities = monitorDataEntity.getDataValues().stream().filter((MonitorDataValueEntity m)
                                    -> m.getAttributeId().equals(monitorData.getAttributeId())).collect(Collectors.toList());
                            MonitorDataValueEntity  attributeEntity = attributeEntities.size()>0?attributeEntities.get(0):null;
                            if (attributeEntity != null) {
                                // 实时数据
                                monitorData.setDataValue(attributeEntity.getDataValue());
                                // 日期算换格式
                                SimpleDateFormat formatdate = new SimpleDateFormat("yyyy-MM-dd");
                                // 计算今日数据
                                if(formatdate.format(new Date()).equals(formatdate.format(monitorDataEntity.getCollectDate()))) {
                                    Double attributeValue = 0d;
                                    if (attributeEntity.getDataValue() != null && monitorData.getLatestValue() != null){
                                        attributeValue = attributeEntity.getDataValue() - monitorData.getLatestValue();
                                    }
                                    setWaterUsage(monitorData.getAttributeType(), monDataCol, attributeValue);
                                }
                                setOnlineDataVo(monitorData.getAttributeType(), monDataCol, monitorData, attributeEntity, pumpStatus);
                            }
                        }
                    }
                }
            }
        }
        for(OnlineDataVo mon : result){
            if (SceneTypeEnum.WATER_SOURCE.getMessage().equals(mon.getSceneTypeName())
                    || SceneTypeEnum.WATER_WORKS.getMessage().equals(mon.getSceneTypeName())){
                if(mon.getYieldWaterUsage()!=null) {
                    mon.setYieldWaterUsage(mon.getYieldWaterUsage() / 10000);
                }
                if(mon.getIntakeWaterUsage()!=null) {
                    mon.setIntakeWaterUsage(mon.getIntakeWaterUsage() / 10000);
                }
                if(mon.getPowerUsage()!=null) {
                    mon.setPowerUsage(mon.getPowerUsage() / 10000);
                }
            }
        }
    }



    private void setMonitorDataCollectVo(String attributeType, MonitorDataCollectVo monDataCol, Double attributeValue){
        switch (attributeType) {
            case "3":
            case "16":
                monDataCol.setYieldWaterUsage(monDataCol.getYieldWaterUsage() != null ? monDataCol.getYieldWaterUsage() + attributeValue : attributeValue);
                break;
            case "4":
                monDataCol.setIntakeWaterUsage(monDataCol.getIntakeWaterUsage() != null ? monDataCol.getIntakeWaterUsage() + attributeValue : attributeValue);
                break;
            case "5":
                monDataCol.setPowerUsage(monDataCol.getPowerUsage() != null ? monDataCol.getPowerUsage() + attributeValue : attributeValue);
                break;
            case "6":
                monDataCol.setDrugUsage(monDataCol.getDrugUsage() != null ? monDataCol.getDrugUsage() + attributeValue : attributeValue);
                break;
            default:
                break;
        }
    }

    private void setWaterUsage(String attributeType, OnlineDataVo monDataCol, Double attributeValue){
        switch (attributeType) {
            // 供水量or出水量
            case "3":
                monDataCol.setYieldWaterUsage(monDataCol.getYieldWaterUsage() != null ? monDataCol.getYieldWaterUsage() + attributeValue : attributeValue);
                break;
            // 取水量or进水量
            case "4":
                monDataCol.setIntakeWaterUsage(monDataCol.getIntakeWaterUsage() != null ? monDataCol.getIntakeWaterUsage() + attributeValue : attributeValue);
                break;
            // 耗电量
            case "5":
                monDataCol.setPowerUsage(monDataCol.getPowerUsage() != null ? monDataCol.getPowerUsage() + attributeValue : attributeValue);
                break;
            // 耗药量
            case "6":
                monDataCol.setDrugUsage(monDataCol.getDrugUsage() != null ? monDataCol.getDrugUsage() + attributeValue : attributeValue);
                break;
            default:
                break;
        }
    }

    private void setOnlineDataVo(String attributeType, OnlineDataVo monDataCol, MonitorDataVo monitorData, MonitorDataValueEntity  attributeEntity, List<MonitorDataVo> pumpStatus){
        switch (attributeType) {
            // 取水PHor进水PH
            case "7":
                monDataCol.setIntakePh(monitorData);
                break;
            // 供水PHor出水PH
            case "8":
                monDataCol.setYieldPh(monitorData);
                break;
            // 取水浊度or进水浊度
            case "9":
                monDataCol.setIntakeTurbidity(monitorData);
                break;
            // 供水浊度or出水浊度
            case "10":
                monDataCol.setYieldTurbidity(monitorData);
                break;
            // 余氯
            case "11":
                monDataCol.setResidualChlorine(monitorData);
                break;
            // 水位
            case "12":
                monDataCol.setWaterLevel(monitorData);
                break;
            // 压力
            case "13":
                monDataCol.setPressure(monitorData);
                break;
            // 瞬时流量
            case "14":
                monDataCol.setInstantFlow(monitorData);
                break;
            // 水泵状态
            case "2":
                //去掉末尾小数点
                DecimalFormat decimalFormat = new DecimalFormat("###################.###########");
                String specsValue = attributeEntity.getDataValue() == null ? null : decimalFormat.format(attributeEntity.getDataValue());
                monitorData.setSpecsName(specsValue == null ? null : deviceAttributeSpecsService.selectSpecsName(attributeEntity.getAttributeId(), specsValue));
                pumpStatus.add(monitorData);
                monDataCol.setPumpStatus(pumpStatus);
                break;
            // 累计流量
            case "16":
                monDataCol.setTotalFlow(monitorData);
                break;
            // 电导率
            case "18":
                monDataCol.setConductivity(monitorData);
                break;
            // 进口压力
            case "20":
                monDataCol.setImportPressure(monitorData);
                break;
            default:
                break;
        }
    }
    /**
     * 获取计算数据总值
     */
    public MonitorDataCollectDto getCalTotalData(List<MonitorDataCollectVo> calculateRes){
        MonitorDataCollectDto result = new MonitorDataCollectDto();
        for(MonitorDataCollectVo calculate :calculateRes){
            result.setSceneTypeName(calculate.getSceneTypeName());
            for(MonitorDataVo monitorData : calculate.getMonitorDataEntities()){
                MonitorDataEntity monitorDataEntity = getCacheData(monitorData.getDeviceCode());
                if (monitorDataEntity == null) {
                    continue;
                }
                // 筛选该设备相同属性的值
                List<MonitorDataValueEntity> attributeEntities = monitorDataEntity.getDataValues().stream().filter((MonitorDataValueEntity m)
                        -> m.getAttributeId().equals(monitorData.getAttributeId())).collect(Collectors.toList());
                MonitorDataValueEntity  attributeEntity = attributeEntities.size() > 0 ? attributeEntities.get(0) : null;
                if (attributeEntity == null) {
                    continue;
                }
                // 日期算换格式
                SimpleDateFormat formatdate = new SimpleDateFormat("yyyy-MM-dd");
                // 计算今日数据
                if (formatdate.format(new Date()).equals(formatdate.format(monitorDataEntity.getCollectDate()))) {
                    Double attributeValue = 0d;
                    if (attributeEntity.getDataValue() != null && monitorData.getLatestValue() != null) {
                        attributeValue = attributeEntity.getDataValue() - monitorData.getLatestValue();
                    }
                    switch (monitorData.getAttributeType()) {
                        // 供水量or出水量
                        case "3":
                            result.setYieldWaterUsage(result.getYieldWaterUsage() != null ? result.getYieldWaterUsage() + attributeValue : attributeValue);
                            break;
                        // 取水量or进水量
                        case "4":
                            result.setIntakeWaterUsage(result.getIntakeWaterUsage() != null ? result.getIntakeWaterUsage() + attributeValue : attributeValue);
                            break;
                        // 耗电量
                        case "5":
                            result.setPowerUsage(result.getPowerUsage() != null ? result.getPowerUsage() + attributeValue : attributeValue);
                            break;
                        // 耗药量
                        case "6":
                            result.setDrugUsage(result.getDrugUsage() != null ? result.getDrugUsage() + attributeValue : attributeValue);
                            break;
                        default:
                            break;
                    }
                }
            }
        }
        if (SceneTypeEnum.WATER_SOURCE.getMessage().equals(result.getSceneTypeName())
                || SceneTypeEnum.WATER_WORKS.getMessage().equals(result.getSceneTypeName())){
            if(result.getYieldWaterUsage()!=null) {
                result.setYieldWaterUsage(result.getYieldWaterUsage() / 10000);
            }
            if(result.getIntakeWaterUsage()!=null) {
                result.setIntakeWaterUsage(result.getIntakeWaterUsage() / 10000);
            }
            if(result.getPowerUsage()!=null) {
                result.setPowerUsage(result.getPowerUsage() / 10000);
            }
        }
        return result;
    }
    @Override
    public List<Map<String, Object>> selectStateCount(OnlineDataDto onlineDataDto) {
        LoginUser loginUser = UserUtil.getCurrentUser();
        onlineDataDto.setTenantId(loginUser.getTenantId());
        onlineDataDto.setProgramItems(loginUser.getProgramItemList());
        onlineDataDto.setUserType(loginUser.getType());
        //1是公司，2是公司及以下，3部门，4部门及以下，5自定义
        onlineDataDto.setPermissonType(loginUser.getPermissonType());
        return onlineMonitorMapper.selectStateCount(onlineDataDto);
    }

    @Override
    public List<AlarmDetailsVo> selectAlarmStatsInfo(AlarmDetailsQueryDto dto){
        List<AlarmDetailsVo> alarmDetailsVos =  onlineMonitorMapper.selectAlarmStatsInfo(dto);
        if (CollectionUtil.isEmpty(alarmDetailsVos)) {
            return new ArrayList<>();
        }
        Map<Long, AlarmDetailsVo> dataMap = new HashMap<>();
        Long sendId  = null;
        long minutes = 0;
        Date startTime = null;
        Date endTime = null;
        Date nowTime = new Date();
        for (AlarmDetailsVo alarmDetails : alarmDetailsVos) {
            sendId = alarmDetails.getId();
            AlarmDetailsVo alarmDetailsVo = dataMap.get(sendId);
            if (alarmDetailsVo == null) {
                alarmDetailsVo = new AlarmDetailsVo();
            }
            endTime   = alarmDetails.getAlarmEndTime() != null ? alarmDetails.getAlarmEndTime() : nowTime;
            startTime = DateUtil.parseDate(dto.getStartTime(), "yyyy-MM-dd HH:mm:ss");
            startTime = startTime.after(alarmDetails.getAlarmStartTime()) ? startTime : alarmDetails.getAlarmStartTime();
            minutes   = DateUtil.minutesBetween(startTime, endTime);
            alarmDetailsVo.setDeviceName(alarmDetails.getDeviceName());
            alarmDetailsVo.setId(sendId);
            alarmDetailsVo.setAlarmCount( alarmDetailsVo.getAlarmCount() + 1 );
            alarmDetailsVo.setAlarmDuration(alarmDetailsVo.getAlarmDuration()  + minutes);
            dataMap.put(sendId, alarmDetailsVo);
        }
        return dataMap.values().stream().collect(Collectors.toList());
    }

}
