package cn.cecep.talroad.service.impl;

import cn.cecep.talroad.common.core.domain.R;
import cn.cecep.talroad.common.core.utils.DateUtils;
import cn.cecep.talroad.common.security.utils.SecurityUtils;
import cn.cecep.talroad.domain.*;
import cn.cecep.talroad.domain.BasDevice;
import cn.cecep.talroad.domain.BasDeviceParam;
import cn.cecep.talroad.domain.BasParam;
import cn.cecep.talroad.feign.BaseRegionService;
import cn.cecep.talroad.mapper.analysis.SRaRealTimeAnalysisCoMapper;
import cn.cecep.talroad.service.analysis.ISRaRealTimeAnalysisConverterService;
import cn.cecep.talroad.vo.FactoryDeviceVo;
import cn.cecep.talroad.enums.EnIndustry;
import cn.cecep.talroad.enums.EnStatTimeType;
import cn.cecep.talroad.enums.OperationTypeEnum;
import cn.cecep.talroad.enums.TimeTypeEnum;
import cn.cecep.talroad.mapper.BasDeviceMapper;
import cn.cecep.talroad.service.*;
import cn.cecep.talroad.util.VoToString;
import cn.cecep.talroad.vo.*;
import cn.cecep.talroad.vo.analysis.CoDeviceTypeCountVO;
import cn.cecep.talroad.vo.query.BasDeviceDCSSystemParamQuery;
import cn.cecep.talroad.vo.query.analysis.SRaRealTimeAnalysisCoQuery;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.stream.CollectorUtil;
import cn.hutool.core.util.ArrayUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Maps;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 设备信息(有组织)Service业务层处理
 *
 * @author szhpt
 * @date 2023-01-10
 */
@Service
public class BasDeviceServiceImpl extends ServiceImpl<BasDeviceMapper, BasDevice> implements IBasDeviceService {
    @Autowired
    private BasDeviceMapper basDeviceMapper;
    @Autowired
    private IBasDeviceParamService basDeviceParamService;
    @Autowired
    private IBasProductionDeviceOperationLogService basProductionDeviceOperationLogService;
    @Autowired
    private IMonDevRealService monDevRealService;
    @Autowired
    private IMonDevHourService monDevHourService;
    @Autowired
    private IMonDevOtherService monDevOtherService;
    @Autowired
    private IMonDevJhRealService monDevJhRealService;
    @Autowired
    private IMonDevJhHourService monDevJhHourService;
    @Autowired
    private IMonDevJhOtherService monDevJhOtherService;
    @Autowired
    private IMonDevSnRealService monDevSnRealService;
    @Autowired
    private IMonDevSnHourService monDevSnHourService;
    @Autowired
    private IMonDevSnOtherService monDevSnOtherService;
    @Autowired
    private IMonDevBlRealService monDevBlRealService;
    @Autowired
    private IMonDevBlHourService monDevBlHourService;
    @Autowired
    private IMonDevBlOtherService monDevBlOtherService;
    @Autowired
    private IMonDevDlRealService monDevDlRealService;
    @Autowired
    private IMonDevDlHourService monDevDlHourService;
    @Autowired
    private IMonDevDlOtherService monDevDlOtherService;
    @Autowired
    private IMonDevFsRealService monDevFsRealService;
    @Autowired
    private IMonDevFsHourService monDevFsHourService;
    @Autowired
    private IMonDevFsOtherService monDevFsOtherService;

    @Autowired
    private IBasDeviceParamService deviceParamService;

    @Autowired
    private IBasParamService paramService;

    @Autowired
    @Qualifier("baseRegionService")
    private BaseRegionService baseRegionService;

    @Autowired
    private IBasDeviceZlConfigService basDeviceZlConfigService;

    @Autowired
    private SRaRealTimeAnalysisCoMapper sRaRealTimeAnalysisCoMapper;


    /**
     * 查询设备信息(有组织)列表
     *
     * @param basDevice 设备信息(有组织)
     * @return 设备信息(有组织)
     */
    @Override
    public List<BasDevice> selectBasDeviceList(BasDevice basDevice) {
        return basDeviceMapper.selectBasDeviceList(basDevice);
    }

    /**
     * 该段代码拷贝自唐山市企业精准减排与管控平台
     * 项目地址：http://10.0.206.25/local_projects/he_bei/tangshan/jian-pai-guan-kong/new-tangshan/gkpt-service.git
     * 类与方法：bw.gkpt.svc.web.main.controller.MonitorController.getDeviceDataByType
     */
    @Override
    public void getDeviceDataByType(String timeType, String industry, String factoryId, String deviceId, String deviceType, String startTime, String endTime, String orderField, String orderType, Page page) {
        EnIndustry enIndustry = EnIndustry.getEnumById(industry);
        if (enIndustry == null) {
            throw new RuntimeException("非法的行业参数：" + industry);
        }

        EnStatTimeType enStatTimeType = EnStatTimeType.getEnumById(timeType);
        if (enStatTimeType == null) {
            enStatTimeType = EnStatTimeType.REAL;
        }
        if (StringUtils.isBlank(orderField)) {
            orderField = "data_time";
        }

        List<String> deviceIds;
        if (StringUtils.isNotBlank(deviceId)) {
            deviceIds = new ArrayList<>(Arrays.asList(deviceId.split(",")));
        } else {
            deviceIds = list(new QueryWrapper<BasDevice>()
                    .eq("factory_id", factoryId)
                    .eq("industry", industry)
                    .eq("type", deviceType)
                    .gt("status", 0)
            ).stream().map(BasDevice::getDeviceId).collect(Collectors.toList());
        }
        if (CollectionUtils.isEmpty(deviceIds)) {
            return;
        }

        // 日期格式统一设置为yyyy-MM-dd HH:mm:ss
        startTime = DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", DateUtils.parseDate(startTime));
        endTime = DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", DateUtils.parseDate(endTime));

        try {
            VoToString.paramThreadLocal.set(paramService.list(new QueryWrapper<BasParam>().eq("status", 1).orderByAsc("show_order")));
            VoToString.deviceThreadLocal.set(listByIds(deviceIds));
            VoToString.deviceParamThreadLocal.set(deviceParamService.list(new QueryWrapper<BasDeviceParam>().in("device_id", deviceIds)));

            if (EnIndustry.GT == enIndustry) {
                if (enStatTimeType == EnStatTimeType.REAL) {
                    List<MonDevGtRealVO> list = monDevRealService.getDataPage(factoryId, deviceIds, startTime, endTime, orderField, orderType, page);
                    List<MonDevGtStringVO> vos = VoToString.voToStringReal_GT(list, deviceType, true);
                    page.setRecords(vos);
                } else if (enStatTimeType == EnStatTimeType.HOUR) {
                    List<MonDevGtVO> list = monDevHourService.getDataPage(factoryId, deviceIds, startTime, endTime, orderField, orderType, page);
                    List<MonDevGtStringVO> vos = VoToString.voToStringOther_GT(list, deviceType, true);
                    page.setRecords(vos);
                } else {
                    List<MonDevGtVO> list = monDevOtherService.getDataPage(factoryId, deviceIds, enStatTimeType.id(), startTime, endTime, orderField, orderType, page);
                    List<MonDevGtStringVO> vos = VoToString.voToStringOther_GT(list, deviceType, true);
                    page.setRecords(vos);
                }
            } else if (EnIndustry.JH == enIndustry) {
                if (enStatTimeType == EnStatTimeType.REAL) {
                    List<MonDevJhRealVo> list = monDevJhRealService.getDataPage(factoryId, deviceIds, startTime, endTime, orderField, orderType, page);
                    List<MonDevJhStringVO> vos = VoToString.voToStringReal_JH(list, deviceType, true);
                    page.setRecords(vos);
                } else if (enStatTimeType == EnStatTimeType.HOUR) {
                    List<MonDevJhVO> list = monDevJhHourService.getDataPage(factoryId, deviceIds, startTime, endTime, orderField, orderType, page);
                    List<MonDevJhStringVO> vos = VoToString.voToStringOther_JH(list, deviceType, true);
                    page.setRecords(vos);
                } else {
                    List<MonDevJhVO> list = monDevJhOtherService.getDataPage(factoryId, deviceIds, enStatTimeType.id(), startTime, endTime, orderField, orderType, page);
                    List<MonDevJhStringVO> vos = VoToString.voToStringOther_JH(list, deviceType, true);
                    page.setRecords(vos);
                }
            } else if (EnIndustry.SN == enIndustry) {
                if (enStatTimeType == EnStatTimeType.REAL) {
                    List<MonDevSnRealVo> list = monDevSnRealService.getDataPage(factoryId, deviceIds, startTime, endTime, orderField, orderType, page);
                    List<MonDevSnStringVO> vos = VoToString.voToStringReal_SN(list, true);
                    page.setRecords(vos);
                } else if (enStatTimeType == EnStatTimeType.HOUR) {
                    List<MonDevSnVO> list = monDevSnHourService.getDataPage(factoryId, deviceIds, startTime, endTime, orderField, orderType, page);
                    List<MonDevSnStringVO> vos = VoToString.voToStringOther_SN(list, true);
                    page.setRecords(vos);
                } else {
                    List<MonDevSnVO> list = monDevSnOtherService.getDataPage(factoryId, deviceIds, enStatTimeType.id(), startTime, endTime, orderField, orderType, page);
                    List<MonDevSnStringVO> vos = VoToString.voToStringOther_SN(list, true);
                    page.setRecords(vos);
                }
            } else if (EnIndustry.BL == enIndustry) {
                if (enStatTimeType == EnStatTimeType.REAL) {
                    List<MonDevBlRealVo> list = monDevBlRealService.getDataPage(factoryId, deviceIds, startTime, endTime, orderField, orderType, page);
                    List<MonDevBlStringVO> vos = VoToString.voToStringReal_BL(list, true);
                    page.setRecords(vos);
                } else if (enStatTimeType == EnStatTimeType.HOUR) {
                    List<MonDevBlVO> list = monDevBlHourService.getDataPage(factoryId, deviceIds, startTime, endTime, orderField, orderType, page);
                    List<MonDevBlStringVO> vos = VoToString.voToStringOther_BL(list, true);
                    page.setRecords(vos);
                } else {
                    List<MonDevBlVO> list = monDevBlOtherService.getDataPage(factoryId, deviceIds, enStatTimeType.id(), startTime, endTime, orderField, orderType, page);
                    List<MonDevBlStringVO> vos = VoToString.voToStringOther_BL(list, true);
                    page.setRecords(vos);
                }
            } else if (EnIndustry.DL == enIndustry) {
                if (enStatTimeType == EnStatTimeType.REAL) {
                    List<MonDevDlRealVo> list = monDevDlRealService.getDataPage(factoryId, deviceIds, startTime, endTime, orderField, orderType, page);
                    List<MonDevDlStringVO> vos = VoToString.voToStringReal_DL(list, true);
                    page.setRecords(vos);
                } else if (enStatTimeType == EnStatTimeType.HOUR) {
                    List<MonDevDlVO> list = monDevDlHourService.getDataPage(factoryId, deviceIds, startTime, endTime, orderField, orderType, page);
                    List<MonDevDlStringVO> vos = VoToString.voToStringOther_DL(list, true);
                    page.setRecords(vos);
                } else {
                    List<MonDevDlVO> list = monDevDlOtherService.getDataPage(factoryId, deviceIds, enStatTimeType.id(), startTime, endTime, orderField, orderType, page);
                    List<MonDevDlStringVO> vos = VoToString.voToStringOther_DL(list, true);
                    page.setRecords(vos);
                }
            } else if (EnIndustry.FS == enIndustry) {
                if (enStatTimeType == EnStatTimeType.REAL) {
                    List<MonDevFsRealVo> list = monDevFsRealService.getDataPage(factoryId, deviceIds, startTime, endTime, orderField, orderType, page);
                    List<MonDevFsStringVO> vos = VoToString.voToStringReal_FS(list, true);
                    page.setRecords(vos);
                } else if (enStatTimeType == EnStatTimeType.HOUR) {
                    List<MonDevFsVO> list = monDevFsHourService.getDataPage(factoryId, deviceIds, startTime, endTime, orderField, orderType, page);
                    List<MonDevFsStringVO> vos = VoToString.voToStringOther_FS(list, true);
                    page.setRecords(vos);
                } else {
                    List<MonDevFsVO> list = monDevFsOtherService.getDataPage(factoryId, deviceIds, enStatTimeType.id(), startTime, endTime, orderField, orderType, page);
                    List<MonDevFsStringVO> vos = VoToString.voToStringOther_FS(list, true);
                    page.setRecords(vos);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            VoToString.paramThreadLocal.remove();
            VoToString.deviceThreadLocal.remove();
            VoToString.deviceParamThreadLocal.remove();
        }
    }

    @Override
    public EChartsVO getDeviceChart(String deviceId, String startTime, String endTime, String timeType) {
        return getDeviceChart(deviceId, startTime, endTime, timeType, null);
    }
    @Override
    public ChartVo getDeviceChart3(String deviceId, String startTime, String endTime, String timeType) {
        BasDevice device = getById(deviceId);
        EChartsVO deviceChart =  getDeviceChart(deviceId, startTime, endTime, timeType, pullWorkingProcedureOptions(device.getIndustry(),device.getType()));
        ChartVo chartVo = new ChartVo();
        if(deviceChart != null){
            chartVo.setLegendData(org.springframework.util.CollectionUtils.isEmpty(deviceChart.getLegendData()) ? new Object[]{} : deviceChart.getLegendData().stream().toArray());
            chartVo.setXsxisData(org.springframework.util.CollectionUtils.isEmpty(deviceChart.getXData()) ? new Object[]{} : deviceChart.getXData().stream().toArray());
            if(!org.springframework.util.CollectionUtils.isEmpty(deviceChart.getSeries())){
                if(ArrayUtil.isEmpty(chartVo.getLegendData())){
                    chartVo.setLegendData(deviceChart.getSeries().stream().map(EChartsVO.SeriesObj::getName).collect(Collectors.toList()).stream().toArray());
                }
                List<Map<Object, Object>> seriesData = Lists.newArrayList();
                List<Map<Object, Object>> yaxisData = Lists.newArrayList();
                deviceChart.getSeries().stream().forEach(item->{
                    Map<Object, Object> map = Maps.newHashMap();
                    map.put("name", item.getName());
                    map.put("unit", item.getUnit());
                    map.put("data", item.getValues());
                    seriesData.add(map);
                    Map<Object, Object> ymap = Maps.newHashMap();
                    ymap.put("name", item.getName());
                    ymap.put("unit", item.getUnit());
                    List<BigDecimal> data = Lists.newArrayList();
                    if(!org.springframework.util.CollectionUtils.isEmpty(item.getValues()) && !org.springframework.util.CollectionUtils.isEmpty(deviceChart.getXData())){
                        for (int i = 0; i < item.getValues().size(); i++) {
                            data.add(item.getValues().get(i)!=null?new BigDecimal(item.getValues().get(i).toString()) : BigDecimal.ZERO);
                        }
                        ymap.put("interval", toInterval(data.stream().max((x1, x2) -> x1.compareTo(x2)).get(), deviceChart.getXData().size()));
                        ymap.put("min", 0);
                        ymap.put("max", data.stream().max((x1, x2) -> x1.compareTo(x2)).get());
                    } else {
                        ymap.put("interval", "");
                        ymap.put("min", 0);
                        ymap.put("max", "");
                    }
                    ymap.put("axisLabelUnit", "");
                    yaxisData.add(ymap);
                });
                chartVo.setSeriesData(seriesData);
                chartVo.setYaxisData(yaxisData);
            }
        } else {
            chartVo.setLegendData(new Object[]{});
            chartVo.setXsxisData(new Object[]{});
            chartVo.setSeriesData(Lists.newArrayList());
            chartVo.setYaxisData(Lists.newArrayList());
        }
        return chartVo;
    }
    @Override
    public ChartVo getDeviceChart5(String deviceId, String startTime, String endTime, String timeType) {
        BasDevice device = getById(deviceId);
        EChartsVO deviceChart =  getDeviceChart(deviceId, startTime, endTime, timeType, pullWorkingProcedureOptionsCo(device.getIndustry(),device.getType()));
        ChartVo chartVo = new ChartVo();
        if(deviceChart != null){
            chartVo.setLegendData(org.springframework.util.CollectionUtils.isEmpty(deviceChart.getLegendData()) ? new Object[]{} : deviceChart.getLegendData().stream().toArray());
            chartVo.setXsxisData(org.springframework.util.CollectionUtils.isEmpty(deviceChart.getXData()) ? new Object[]{} : deviceChart.getXData().stream().toArray());
            if(!org.springframework.util.CollectionUtils.isEmpty(deviceChart.getSeries())){
                if(ArrayUtil.isEmpty(chartVo.getLegendData())){
                    chartVo.setLegendData(deviceChart.getSeries().stream().map(EChartsVO.SeriesObj::getName).collect(Collectors.toList()).stream().toArray());
                }
                List<Map<Object, Object>> seriesData = Lists.newArrayList();
                List<Map<Object, Object>> yaxisData = Lists.newArrayList();
                deviceChart.getSeries().stream().forEach(item->{
                    Map<Object, Object> map = Maps.newHashMap();
                    map.put("name", item.getName());
                    map.put("unit", item.getUnit());
                    map.put("data", item.getValues());
                    seriesData.add(map);
                    Map<Object, Object> ymap = Maps.newHashMap();
                    ymap.put("name", item.getName());
                    ymap.put("unit", item.getUnit());
                    List<BigDecimal> data = Lists.newArrayList();
                    if(!org.springframework.util.CollectionUtils.isEmpty(item.getValues()) && !org.springframework.util.CollectionUtils.isEmpty(deviceChart.getXData())){
                        for (int i = 0; i < item.getValues().size(); i++) {
                            data.add(item.getValues().get(i)!=null?new BigDecimal(item.getValues().get(i).toString()) : BigDecimal.ZERO);
                        }
                        ymap.put("interval", toInterval(data.stream().max((x1, x2) -> x1.compareTo(x2)).get(), deviceChart.getXData().size()));
                        ymap.put("min", 0);
                        ymap.put("max", data.stream().max((x1, x2) -> x1.compareTo(x2)).get());
                    } else {
                        ymap.put("interval", "");
                        ymap.put("min", 0);
                        ymap.put("max", "");
                    }
                    ymap.put("axisLabelUnit", "");
                    yaxisData.add(ymap);
                });
                chartVo.setSeriesData(seriesData);
                chartVo.setYaxisData(yaxisData);
            }
        } else {
            chartVo.setLegendData(new Object[]{});
            chartVo.setXsxisData(new Object[]{});
            chartVo.setSeriesData(Lists.newArrayList());
            chartVo.setYaxisData(Lists.newArrayList());
        }
        return chartVo;
    }
    @Override
    public ChartVo getDeviceChart6(String deviceId, String startTime, String endTime, String timeType) {
        BasDevice device = getById(deviceId);
        EChartsVO deviceChart =  getDeviceChartGT(deviceId, startTime, endTime, timeType, pullWorkingProcedureOptionsCo6(device.getIndustry(),"煤气放散火炬"));
        ChartVo chartVo = new ChartVo();
        if(deviceChart != null){
            chartVo.setLegendData(org.springframework.util.CollectionUtils.isEmpty(deviceChart.getLegendData()) ? new Object[]{} : deviceChart.getLegendData().stream().toArray());
            chartVo.setXsxisData(org.springframework.util.CollectionUtils.isEmpty(deviceChart.getXData()) ? new Object[]{} : deviceChart.getXData().stream().toArray());
            if(!org.springframework.util.CollectionUtils.isEmpty(deviceChart.getSeries())){
                if(ArrayUtil.isEmpty(chartVo.getLegendData())){
                    chartVo.setLegendData(deviceChart.getSeries().stream().map(EChartsVO.SeriesObj::getName).collect(Collectors.toList()).stream().toArray());
                }
                List<Map<Object, Object>> seriesData = Lists.newArrayList();
                List<Map<Object, Object>> yaxisData = Lists.newArrayList();
                deviceChart.getSeries().stream().forEach(item->{
                    Map<Object, Object> map = Maps.newHashMap();
                    map.put("name", item.getName());
                    map.put("unit", item.getUnit());
                    map.put("data", item.getValues());
                    seriesData.add(map);
                    Map<Object, Object> ymap = Maps.newHashMap();
                    ymap.put("name", item.getName());
                    ymap.put("unit", item.getUnit());
                    List<BigDecimal> data = Lists.newArrayList();
                    if(!org.springframework.util.CollectionUtils.isEmpty(item.getValues()) && !org.springframework.util.CollectionUtils.isEmpty(deviceChart.getXData())){
                        for (int i = 0; i < item.getValues().size(); i++) {
                            data.add(item.getValues().get(i)!=null?new BigDecimal(item.getValues().get(i).toString()) : BigDecimal.ZERO);
                        }
                        ymap.put("interval", toInterval(data.stream().max((x1, x2) -> x1.compareTo(x2)).get(), deviceChart.getXData().size()));
                        ymap.put("min", 0);
                        ymap.put("max", data.stream().max((x1, x2) -> x1.compareTo(x2)).get());
                    } else {
                        ymap.put("interval", "");
                        ymap.put("min", 0);
                        ymap.put("max", "");
                    }
                    ymap.put("axisLabelUnit", "");
                    yaxisData.add(ymap);
                });
                chartVo.setSeriesData(seriesData);
                chartVo.setYaxisData(yaxisData);
            }
        } else {
            chartVo.setLegendData(new Object[]{});
            chartVo.setXsxisData(new Object[]{});
            chartVo.setSeriesData(Lists.newArrayList());
            chartVo.setYaxisData(Lists.newArrayList());
        }
        return chartVo;
    }

    @Override
    public List<BasDeviceVo.CoalDiffuse> getCoalDiffuseList(String deviceName, String status) {
        return basDeviceMapper.selectCoalDiffuseList(deviceName, status, null);
    }

    /**
     * 装备启停分析参数
     * @param industryCategoryCode
     * @param workingProcedure
     * @return
     */
    public List<AmProblemFiVo.PollutantVo> pullWorkingProcedureOptions(String industryCategoryCode,String workingProcedure) {
        List<AmProblemFiVo.PollutantVo> map=new ArrayList<>();
        if(industryCategoryCode.equals("GT")&&workingProcedure.equals("SL")){
            List<String> numbers = Arrays.asList("p1", "p2", "g604","g921", "o2Out");
            numbers.forEach(item->{
                AmProblemFiVo.PollutantVo objectMap=new AmProblemFiVo.PollutantVo();
                objectMap.setProp(item);
                map.add(objectMap);
            });
        }
        if(industryCategoryCode.equals("GT")&&workingProcedure.equals("GL")){
            List<String> numbers = Arrays.asList("p1","p2", "p4", "g930","g932");
            numbers.forEach(item->{
                AmProblemFiVo.PollutantVo objectMap=new AmProblemFiVo.PollutantVo();
                objectMap.setProp(item);
                map.add(objectMap);
            });
        }
        if(industryCategoryCode.equals("GT")&&workingProcedure.equals("SJJ")){
            List<String> numbers = Arrays.asList("p1","p2","p3","g604","g912","g914","g917","o2Out");
            numbers.forEach(item->{
                AmProblemFiVo.PollutantVo objectMap=new AmProblemFiVo.PollutantVo();
                objectMap.setProp(item);
                map.add(objectMap);
            });
        }
        if(industryCategoryCode.equals("GT")&&workingProcedure.equals("LY")){
            List<String> numbers = Arrays.asList("p1", "p2", "o2Out");
            numbers.forEach(item->{
                AmProblemFiVo.PollutantVo objectMap=new AmProblemFiVo.PollutantVo();
                objectMap.setProp(item);
                map.add(objectMap);
            });
        }
        if(industryCategoryCode.equals("GT")&&workingProcedure.equals("FDJZ")){
            List<String> numbers = Arrays.asList("p1", "p3", "g942", "o2Out");
            numbers.forEach(item->{
                AmProblemFiVo.PollutantVo objectMap=new AmProblemFiVo.PollutantVo();
                objectMap.setProp(item);
                map.add(objectMap);
            });
        }
//        if(industryCategoryCode.equals("GT")&&workingProcedure.equals("焦炉")){
//            List<String> numbers = Arrays.asList("球团", "炼铁", "烧结","白灰窑","发电","焦炉");
//            numbers.forEach(item->{
//                Map<String, Object> objectMap=new HashMap<>();
//                objectMap.put("label",item);
//                objectMap.put("value",item);
//                map.add(objectMap);
//            });
//        }
//        if(industryCategoryCode.equals("JH")&&workingProcedure.equals("焦炉")){
//            List<String> numbers = Arrays.asList("焦炉");
//            numbers.forEach(item->{
//                Map<String, Object> objectMap=new HashMap<>();
//                objectMap.put("label",item);
//                objectMap.put("value",item);
//                map.add(objectMap);
//            });
//        }
        if(industryCategoryCode.equals("SN")&&workingProcedure.equals("SNY")){
            List<String> numbers = Arrays.asList("ss100");
            numbers.forEach(item->{
                AmProblemFiVo.PollutantVo objectMap=new AmProblemFiVo.PollutantVo();
                objectMap.setProp(item);
                map.add(objectMap);
            });
        }
        if(industryCategoryCode.equals("BL")&&workingProcedure.equals("SCX")){
            List<String> numbers = Arrays.asList("bs102","bs107");
            numbers.forEach(item->{
                AmProblemFiVo.PollutantVo objectMap=new AmProblemFiVo.PollutantVo();
                objectMap.setProp(item);
                map.add(objectMap);
            });
        }
        if(industryCategoryCode.equals("FS")&&workingProcedure.equals("FSL")){
            List<String> numbers = Arrays.asList("fs100","gc19","gc21","fs101","gc30");
            numbers.forEach(item->{
                AmProblemFiVo.PollutantVo objectMap=new AmProblemFiVo.PollutantVo();
                objectMap.setProp(item);
                map.add(objectMap);
            });
        }
        if(industryCategoryCode.equals("DL")&&workingProcedure.equals("GUL")){
            List<String> numbers = Arrays.asList("g903","hs101","g905");
            numbers.forEach(item->{
                AmProblemFiVo.PollutantVo objectMap=new AmProblemFiVo.PollutantVo();
                objectMap.setProp(item);
                map.add(objectMap);
            });
        }
        return map;
    }

    /**
     * co分析参数
     * @param industryCategoryCode
     * @param workingProcedure
     * @return
     */
    public List<AmProblemFiVo.PollutantVo> pullWorkingProcedureOptionsCo(String industryCategoryCode,String workingProcedure) {
        List<AmProblemFiVo.PollutantVo> map=new ArrayList<>();
        if(industryCategoryCode.equals("GT")&&workingProcedure.equals("GLMQ")){
            List<String> numbers = Arrays.asList("mq1","mq4","mq5","mq3", "mq6");
            numbers.forEach(item->{
                AmProblemFiVo.PollutantVo objectMap=new AmProblemFiVo.PollutantVo();
                objectMap.setProp(item);
                map.add(objectMap);
            });
        }
        if(industryCategoryCode.equals("GT")&&workingProcedure.equals("MQGW")){
            List<String> numbers = Arrays.asList("g979", "js202","js201","g980");
            numbers.forEach(item->{
                AmProblemFiVo.PollutantVo objectMap=new AmProblemFiVo.PollutantVo();
                objectMap.setProp(item);
                map.add(objectMap);
            });
        }
        if(industryCategoryCode.equals("JH")&&workingProcedure.equals("MQGW")){
            List<String> numbers = Arrays.asList("g979", "js202","js201","g980");
            numbers.forEach(item->{
                AmProblemFiVo.PollutantVo objectMap=new AmProblemFiVo.PollutantVo();
                objectMap.setProp(item);
                map.add(objectMap);
            });
        }
        if(industryCategoryCode.equals("GT")&&workingProcedure.equals("ZL")){
            List<String> numbers = Arrays.asList("p1","p2");
            numbers.forEach(item->{
                AmProblemFiVo.PollutantVo objectMap=new AmProblemFiVo.PollutantVo();
                objectMap.setProp(item);
                map.add(objectMap);
            });
        }
        if(industryCategoryCode.equals("GT")&&workingProcedure.equals("GLMQG")){
            List<String> numbers = Arrays.asList("b806");
            numbers.forEach(item->{
                AmProblemFiVo.PollutantVo objectMap=new AmProblemFiVo.PollutantVo();
                objectMap.setProp(item);
                map.add(objectMap);
            });
        }
        return map;
    }
    /**
     * co分析参数
     * @param industryCategoryCode
     * @param workingProcedure
     * @return
     */
    public List<AmProblemFiVo.PollutantVo> pullWorkingProcedureOptionsCo6(String industryCategoryCode,String workingProcedure) {
        List<AmProblemFiVo.PollutantVo> map=new ArrayList<>();
        if(industryCategoryCode.equals("GT")&&workingProcedure.equals("煤气放散火炬")){
            List<String> numbers = Arrays.asList("mq5");
            numbers.forEach(item->{
                AmProblemFiVo.PollutantVo objectMap=new AmProblemFiVo.PollutantVo();
                objectMap.setProp(item);
                map.add(objectMap);
            });
        }
        return map;
    }

    @Override
    public EChartsVO getDeviceChart(String deviceId, String startTime, String endTime, String timeType, List<AmProblemFiVo.PollutantVo> pollutantVos) {
        BasDevice device = getById(deviceId);

        if (device == null) {
            throw new RuntimeException("获取设备图表异常，设备不存在（id = " + deviceId + "）");
        }
        // x轴数据
        List<String> xdata = DateUtils.getRangeTimes(timeType, startTime, endTime);

        Page page = new Page(1, 14400);
        getDeviceDataByType(
                timeType,
                device.getIndustry(),
                device.getFactoryId(),
                device.getDeviceId(), device.getType(), startTime, endTime, null, "asc", page);

        // 分页数据返回类型不确定，通过格式化为json后，统一转为map列表
        String json = JSON.toJSONString(page.getRecords());
        List<Map<String, Object>> mapList = JSON.parseObject(json, new TypeReference<List<Map<String, Object>>>() {
        }.getType());

        // 以时间为key 转为map，日期格式要保证与x轴格式一样
        Map<String, Map<String, Object>> dataMap = mapList.stream().collect(Collectors.toMap(o -> {
                    Date date = DateUtils.parseDate(o.get("dataTime"));
                    if (timeType.equals("R")) {
                        return DateUtils.parseDateToStr("yyyy-MM-dd HH:mm", date);
                    } else if (timeType.equals(TimeTypeEnum.HOUR.getCode())) {
                        return DateUtils.parseDateToStr("yyyy-MM-dd HH", date);
                    } else {
                        return DateUtils.parseDateToStr("yyyy-MM-dd", date);
                    }
                }, o -> o,
                // TODO 数据问题导致存在key相同的，暂取第一条
                (o1, o2) -> o1));

        List<BasParam> basParams = paramService.list(new QueryWrapper<BasParam>()
                .eq("status", 1)
                .eq("industry", device.getIndustry())
                .eq("device_type", device.getType())
                .eq("data_type_java", "Double") // 曲线图展示只查数字类型参数
                .isNotNull("param_code_svc")
                .orderByAsc("show_order"));
        Map<String, BasParam> basParamMap = basParams.stream().collect(Collectors.toMap(BasParam::getParamCodeSvc, o -> o, (o1, o2) -> o1));

        /*
            将查询到的监测数据转为曲线图要求的格式
         */
        List<EChartsVO.SeriesObj> series = new ArrayList<>();

        // 若pollutantVos不为null，则只展示指定的监测参数。（若指定的参数集合是空的，则返回空数据）
        if (pollutantVos != null) {
            for (AmProblemFiVo.PollutantVo pollutantVo : pollutantVos) {
                BasParam param = basParamMap.get(pollutantVo.getProp());
                if (param == null) {
                    continue;
                }
                EChartsVO.SeriesObj ser = new EChartsVO.SeriesObj();
                ser.setName(param.getFacilityName() + "-" + param.getName());
                ser.setUnit(param.getUnitReal() == null ? "" : param.getUnitReal());
                ser.setOther(param.getFacilityType());
                ser.setProp(param.getParamCodeSvc());
                ser.setMarkLine(pollutantVo.getMarkLine());
                ser.setMarkArea(pollutantVo.getMarkArea());

                // 遍历x轴数据，保证x轴与系列数据一一对应
                List<Object> values = xdata.stream().map(o -> {
                    Map<String, Object> map = dataMap.get(o);
                    if (map == null) {
                        return null;
                    }
                    Object value = map.get(param.getParamCodeSvc());
                    if ("(共用)".equals(value)) {
                        return null;
                    }
                    return value;
                }).collect(Collectors.toList());
                ser.setValues(values);

                series.add(ser);
            }
        } else { // 未指定监测参数，默认展示所有的

            for (BasParam param : basParams) {
                EChartsVO.SeriesObj ser = new EChartsVO.SeriesObj();
                ser.setName(param.getFacilityName() + "-" + param.getName());
                ser.setUnit(param.getUnitReal() == null ? "" : param.getUnitReal());
                ser.setOther(param.getFacilityType());
                ser.setProp(param.getParamCodeSvc());

                // 遍历x轴数据，保证x轴与系列数据一一对应
                List<Object> values = xdata.stream().map(o -> {
                    Map<String, Object> map = dataMap.get(o);
                    if (map == null) {
                        return null;
                    }
                    Object value = map.get(param.getParamCodeSvc());
                    if ("(共用)".equals(value)) {
                        return null;
                    }
                    return value;
                }).collect(Collectors.toList());
                ser.setValues(values);
                series.add(ser);
            }

        }
        EChartsVO chartsVO = new EChartsVO();
        chartsVO.setXData(xdata);
        chartsVO.setSeries(series);
        return chartsVO;
    }

    /**
     * 展示钢铁转炉对应的多个设备煤气放散火炬
     * @param deviceId
     * @param startTime
     * @param endTime
     * @param timeType
     * @param pollutantVos
     * @return
     */
    public EChartsVO getDeviceChartGT(String deviceId, String startTime, String endTime, String timeType, List<AmProblemFiVo.PollutantVo> pollutantVos) {
        BasDevice device = getById(deviceId);
        List<BasDeviceZlConfig> deviceIds = basDeviceZlConfigService.list(new QueryWrapper<BasDeviceZlConfig>().eq("device_id", deviceId));
        if(CollectionUtils.isEmpty(deviceIds)){
            return null;
        }
        String collect = deviceIds.stream().map(d -> d.getFsDeviceId()).collect(Collectors.joining(","));
        if (device == null) {
            throw new RuntimeException("获取设备图表异常，设备不存在（id = " + deviceId + "）");
        }
        Page page = new Page(1, 14400);
        getDeviceDataByType(
                timeType,
                device.getIndustry(),
                device.getFactoryId(),
                collect, "ZLMQ", startTime, endTime, null, "asc", page);

        // 分页数据返回类型不确定，通过格式化为json后，统一转为map列表
        String json = JSON.toJSONString(page.getRecords());
        List<Map<String, Object>> mapList = JSON.parseObject(json, new TypeReference<List<Map<String, Object>>>() {
        }.getType());

        // x轴数据
        List<String> xdata = DateUtils.getRangeTimes(timeType, startTime, endTime);
        Map<String, List<Map<String, Object>>> listMap =
                mapList.stream().collect(
                        Collectors.groupingBy(item -> item.get("name").toString())
                );
        // 以时间为key 转为map，日期格式要保证与x轴格式一样
        List<BasParam> basParams = paramService.list(new QueryWrapper<BasParam>()
                .eq("status", 1)
                .eq("industry", device.getIndustry())
                .eq("device_type", device.getType())
                .eq("data_type_java", "Double") // 曲线图展示只查数字类型参数
                .isNotNull("param_code_svc")
                .orderByAsc("show_order"));
        Map<String, BasParam> basParamMap = basParams.stream().collect(Collectors.toMap(BasParam::getParamCodeSvc, o -> o, (o1, o2) -> o1));

        /*
            将查询到的监测数据转为曲线图要求的格式
         */
        List<EChartsVO.SeriesObj> series = new ArrayList<>();

        // 若pollutantVos不为null，则只展示指定的监测参数。（若指定的参数集合是空的，则返回空数据）
        listMap.forEach((key,value)->{
            EChartsVO.SeriesObj ser = new EChartsVO.SeriesObj();
            ser.setName(key + "-" + "放散口温度");
            ser.setUnit("℃");
            ser.setOther("MQ");
            ser.setProp("mq5");
            Map<String, Map<String, Object>> dataMap = value.stream().collect(Collectors.toMap(o -> {
                        Date date = DateUtils.parseDate(o.get("dataTime"));
                        if (timeType.equals("R")) {
                            return DateUtils.parseDateToStr("yyyy-MM-dd HH:mm", date);
                        } else if (timeType.equals(TimeTypeEnum.HOUR.getCode())) {
                            return DateUtils.parseDateToStr("yyyy-MM-dd HH", date);
                        } else {
                            return DateUtils.parseDateToStr("yyyy-MM-dd", date);
                        }
                    }, o -> o,
                    // TODO 数据问题导致存在key相同的，暂取第一条
                    (o1, o2) -> o1));
            // 遍历x轴数据，保证x轴与系列数据一一对应
            List<Object> values = xdata.stream().map(o -> {
                Map<String, Object> map = dataMap.get(o);
                if (map == null) {
                    return null;
                }
                return map.get("mq5");
            }).collect(Collectors.toList());
            ser.setValues(values);
            series.add(ser);
        });
        EChartsVO chartsVO = new EChartsVO();
        chartsVO.setXData(xdata);
        chartsVO.setSeries(series);
        return chartsVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void editBatch(BasDeviceVo[] basDeviceVoArr) {
        List<BasDeviceVo> basDeviceSiteVoList = Arrays.asList(basDeviceVoArr);
        //赋值
        List<BasDevice> basDeviceList = new ArrayList<>();
        basDeviceSiteVoList.forEach(e -> {
            BasDevice basDevice = new BasDevice();
            BeanUtil.copyProperties(e, basDevice);
            basDeviceList.add(basDevice);
        });


        //记录操作日志
        List<BasProductionDeviceOperationLog> basProductionDeviceOperationLogList = new ArrayList<>();
        basDeviceList.forEach(e -> {
            BasProductionDeviceOperationLog basProductionDeviceOperationLog = new BasProductionDeviceOperationLog();

            BasDevice basDevice = this.getById(e.getDeviceId());
            String uuid = UUID.randomUUID().toString().trim().replaceAll("-", "");
            basProductionDeviceOperationLog.setLogId(uuid);
            basProductionDeviceOperationLog.setFactoryId(basDevice.getFactoryId());
            basProductionDeviceOperationLog.setOperationTime(DateUtils.parseFormatDate("yyyy-MM-dd HH:mm:ss", new Date()));
            basProductionDeviceOperationLog.setOperationStatus(OperationTypeEnum.UPDATE_OPERATION.getName());
            basProductionDeviceOperationLog.setOperator(SecurityUtils.getLoginUser().getSysUser().getUserName());
            basProductionDeviceOperationLog.setOperatorId(SecurityUtils.getLoginUser().getSysUser().getUserId() + "");

            basProductionDeviceOperationLog.setBeforeModifyLag(basDevice.getLatMap());
            basProductionDeviceOperationLog.setBeforeModifyLng(basDevice.getLonMap());
            basProductionDeviceOperationLog.setAfterModifyLag(e.getLatMap());
            basProductionDeviceOperationLog.setAfterModifyLng(e.getLonMap());
            basProductionDeviceOperationLog.setDeviceName(basDevice.getName());
            basProductionDeviceOperationLog.setWorkProcedure(basDevice.getWorkStep());
            basProductionDeviceOperationLogList.add(basProductionDeviceOperationLog);

        });
        basDeviceMapper.updateBatchCoordinate(basDeviceSiteVoList);
        basProductionDeviceOperationLogService.saveBatch(basProductionDeviceOperationLogList);
    }


    @Override
    public List<String> groupByWorkStepSelect(String factoryId, String industryCategory) {
        return basDeviceMapper.groupByWorkStepSelect(factoryId, industryCategory);
    }

    @Override
    public IPage<BasDeviceDCSSystemParamVo> listDCSSystemParam(BasDeviceDCSSystemParamQuery query) {
        Page<BasDeviceDCSSystemParamVo> page = new Page<>(query.getPageNum(), query.getPageSize());
        IPage<BasDeviceDCSSystemParamVo> basDeviceDCSSystemParamVoIPage = basDeviceMapper.listDCSSystemParam(page, query);
        List<BasDeviceDCSSystemParamVo> records = basDeviceDCSSystemParamVoIPage.getRecords();
        if (CollectionUtils.isNotEmpty(records)) {
            List<String> deviceIdList = records.stream().map(BasDeviceDCSSystemParamVo::getDeviceId).collect(Collectors.toList());
//            List<BasDeviceParam> basDeviceParamList = basDeviceParamService.list(wrapper);
            List<BasDeviceParamListVo> basDeviceParamList = basDeviceParamService.queryByDeviceIdListAndIndustry(deviceIdList,query.getIndustry(), query.getParamName());
            Map<String, List<BasDeviceParamListVo>> deviceIdListMap = basDeviceParamList.stream().collect(Collectors.groupingBy(BasDeviceParamListVo::getDeviceId));
            records.forEach(e -> {
                e.setBasDeviceParamList(deviceIdListMap.get(e.getDeviceId()));
            });

        }
        return basDeviceDCSSystemParamVoIPage;
    }

    @Override
    public List<BasDeviceDCSSystemParamExcelVo> exportDCSSystemParam(BasDeviceDCSSystemParamQuery query) {
        List<BasDeviceDCSSystemParamExcelVo> basDeviceDCSSystemParamVoIPage = basDeviceMapper.exportDCSSystemParam(query);
        return basDeviceDCSSystemParamVoIPage;
    }

    @Override
    public List<String> groupByParamNameSelect(String factoryId, String industryCategory) {
        return basDeviceMapper.groupByParamNameSelect(factoryId, industryCategory);
    }

    @Override
    public FactoryDeviceVo selectFactoryDeviceVoByDeviceId(String deviceId) {

        return basDeviceMapper.selectFactoryDeviceVoByDeviceId(deviceId);
    }

    @Override
    public EChartsVO getDeviceStatusChart(BasDeviceVo.SimpleStatusVo deviceVo, String startTime, String endTime) {
        // x轴数据
        List<String> xdata = DateUtils.getRangeTimes("EL".equals(deviceVo.getIndustry()) ? "QH" : "M", startTime, endTime);

        List<Map<String, Object>> list = basDeviceMapper.selectDeviceStatusChart(deviceVo.getDeviceId(), startTime, endTime);

        Map<String, String> timeStatusMap = list.stream().collect(
                Collectors.toMap(
                        o -> DateUtils.parseDateToStr("yyyy-MM-dd HH:mm", (Date) o.get("time")),
                        o -> (String) o.get("status"),
                        (o1, o2) -> o1)
        );

        // 若是dcs设备（行业不是El，则认为是dcs），10分钟分析一次，把这10分钟的都当做这个状态来判断
        if (!"EL".equals(deviceVo.getIndustry())) {
            for (Map<String, Object> map : list) {
                Date d = (Date) map.get("time");
                String status = (String) map.get("status");

                for (int i = 1; i <= 9; i++) {
                    String key = DateUtils.parseDateToStr("yyyy-MM-dd HH:mm", DateUtils.addMinutes(d, -i));
                    timeStatusMap.putIfAbsent(key, status);
                }
            }
        }

        EChartsVO.SeriesObj ser1 = new EChartsVO.SeriesObj();
        ser1.setName("运行");
        ser1.setProp("1");
        ser1.setValues(new ArrayList<>());

        EChartsVO.SeriesObj ser2 = new EChartsVO.SeriesObj();
        ser2.setName("停运");
        ser2.setProp("2");
        ser2.setValues(new ArrayList<>());

        EChartsVO.SeriesObj ser3 = new EChartsVO.SeriesObj();
        ser3.setName("启停");
        ser3.setProp("3");
        ser3.setValues(new ArrayList<>());

        EChartsVO.SeriesObj ser4 = new EChartsVO.SeriesObj();
        ser4.setName("停启");
        ser4.setProp("4");
        ser4.setValues(new ArrayList<>());

        EChartsVO.SeriesObj ser5 = new EChartsVO.SeriesObj();
        ser5.setName("数据缺失");
        ser5.setProp("5");
        ser5.setValues(new ArrayList<>());

        EChartsVO chartsVO = new EChartsVO();
        chartsVO.setXData(xdata);
        chartsVO.setSeries(Arrays.asList(ser1, ser2, ser3, ser4, ser5));

        /*
            填充系列值
         */

        // 遍历x轴，保证系列值与x轴刻度一一对应
        for (String time : xdata) {
            String status = timeStatusMap.get(time);

            for (EChartsVO.SeriesObj ser : chartsVO.getSeries()) {
                // 若系列的prop属性与状态码相等，则设置系列值为状态码，否则填充null
                if (ser.getProp().equals(status)) {
                    ser.getValues().add(status);
                } else {
                    ser.getValues().add(null);
                }
            }
        }
        return chartsVO;
    }

    @Override
    public BasDeviceVo.CountOverview getCountOverview() {
        String userRegionCode = SecurityUtils.getLoginUser().getSysUser().getRegionCode();
        if (StringUtils.isEmpty(userRegionCode)) {
            return new BasDeviceVo.CountOverview();
        }
        R<List<String>> r = baseRegionService.getRegionCodeListChild(userRegionCode);
        if (r.getCode() != R.SUCCESS) {
            return new BasDeviceVo.CountOverview();
        }
        BasDeviceVo.CountOverview countOverview = basDeviceMapper.selectCountOverview(r.getData());
        return countOverview;
    }

    @Override
    public BasDeviceVo.CoalCountOverview getCoalCountOverview() {
        String userRegionCode = SecurityUtils.getLoginUser().getSysUser().getRegionCode();
        if (StringUtils.isEmpty(userRegionCode)) {
            return new BasDeviceVo.CoalCountOverview();
        }
        R<List<String>> r = baseRegionService.getRegionCodeListChild(userRegionCode);
        if (r.getCode() != R.SUCCESS) {
            return new BasDeviceVo.CoalCountOverview();
        }

        BasDeviceVo.CoalCountOverview countOverview = basDeviceMapper.selectCoalCountOverview(r.getData());

        String ymd = DateUtils.parseDateToStr("yyyy-MM-dd", new Date());
        SRaRealTimeAnalysisCoQuery coQuery = new SRaRealTimeAnalysisCoQuery();
        coQuery.setAnalyseStartTime(ymd + " 00:00");
        coQuery.setAnalyseEndTime(ymd + " 23:59");
        coQuery.setIndustryCategoryCode("GT");
        CoDeviceTypeCountVO gtCountVO = sRaRealTimeAnalysisCoMapper.selectDeviceTypeCount(coQuery);

        if (gtCountVO != null) {
            countOverview.setGtGLMQCount(gtCountVO.getGLMQCount());
            countOverview.setGtGLMQGCount(gtCountVO.getGLMQGCount());
            countOverview.setGtZLCount(gtCountVO.getZLCount());
            countOverview.setGtMQGWCount(gtCountVO.getMQGWCount());
        }

        coQuery.setIndustryCategoryCode("JH");
        CoDeviceTypeCountVO jhCountVO = sRaRealTimeAnalysisCoMapper.selectDeviceTypeCount(coQuery);
        if (jhCountVO != null) {
            countOverview.setJhMQGWCount(jhCountVO.getMQGWCount());
        }
        return countOverview;
    }

    @Override
    public EChartsVO getDeviceChart(String deviceId, String startTime, String endTime) {
        return getDeviceChart(deviceId, startTime, endTime, "R");
    }

    private BigDecimal toInterval(BigDecimal max, Integer size){
        return max.divide(new BigDecimal(size),1,BigDecimal.ROUND_HALF_UP);
    }
}
