package cn.wise.sc.energy.power.plant.business.task;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.wise.sc.energy.power.plant.business.bean.DataPower;
import cn.wise.sc.energy.power.plant.business.domain.CharacterParamInfo;
import cn.wise.sc.energy.power.plant.business.domain.vo.CharacterParamInfoVo;
import cn.wise.sc.energy.power.plant.business.opentsdb.OpentsdbOkHttpClient;
import cn.wise.sc.energy.power.plant.business.service.ICharacterParamService;
import cn.wise.sc.energy.power.plant.business.service.IEventInfoService;
import cn.wise.sc.energy.power.plant.business.service.impl.EventInfoServiceImpl;
import cn.wise.sc.energy.power.plant.business.task.schedule.ScheduleTask;
import com.alibaba.fastjson.JSON;
import net.opentsdb.client.api.query.response.QueryResponse;
import net.opentsdb.client.bean.QueryResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @author neo.shu
 * @since 2020/9/17 17:30
 */
@Service(value = "indexRealTimeTask")
public class IndexRealTimeTask extends ScheduleTask {


    @Autowired
    ICharacterParamService iCharacterParamService;
    @Autowired
    IEventInfoService iEventInfoService;

    @Autowired
    TaskCacheDataService taskCacheDataService;

    public IndexRealTimeTask() {
        super(UUID.randomUUID().toString());
    }

    @Override
    public void run() {
        ConcurrentHashMap<String, IndexRealTimeWebSocket> webSocketMap =
                IndexRealTimeWebSocket.webSocketMap;
        ConcurrentHashMap<String, String> deviceMap = IndexRealTimeWebSocket.deviceMap;
        //给每个deviceid分组，然后统一查询，进行推送
        Map<String, List<Map.Entry<String, String>>> groupMap = deviceMap.entrySet().stream().collect(Collectors.groupingBy(c -> c.getValue()));
        //需要区分的测点
        String[] points = new String[]{
                //右上
                "定子CA线电压",
                "定子AB线电压",
                "定子CB线电压",
                "定子A相电流",
                "定子B相电流",
                "定子C相电流",
                //右中
                "汽端轴振X",
                "汽端轴振Y",
                "励端轴振X",
                "励端轴振Y",
                //右下
                "汽端轴瓦温度1",
                "励端轴瓦温度1",
                "集电环轴瓦温度1",
                //左下极坐标
                "层间温度",
                "上层线圈出水温度",
                "下层线圈出水温度",

                //中间
                "转速1",
                "有功功率",
        };

        //向每个webSocket推送系统实时数据
        List<CharacterParamInfoVo> characterParamInfoList = taskCacheDataService.cacheIndexCPI();
        for (String deviceId : groupMap.keySet()) {
            //获取kkscode
            List<CharacterParamInfoVo> characterParamInfoVos;
            if ("total".equals(deviceId)) {
                characterParamInfoVos = characterParamInfoList;
            } else {
                characterParamInfoVos = characterParamInfoList.stream().filter(item -> item.getDeviceId().equals(deviceId)).collect(Collectors.toList());
            }
            Map<String, String> KKsCodes = characterParamInfoVos.stream().filter(item ->
                    IS_CONTAINS(item.getCpName(), points))
                    .collect(Collectors.toMap(CharacterParamInfoVo::getKksCode, CharacterParamInfoVo::getCpName));
            Map<String, String> KKsCodes_cunit = characterParamInfoVos.stream().filter(item ->
                    IS_CONTAINS(item.getCpName(), points))
                    .collect(Collectors.toMap(CharacterParamInfoVo::getKksCode, CharacterParamInfoVo::getCpUnit));
            List<QueryResult> queryResults = new ArrayList<>();
            List<Object> xAxis = new ArrayList<>();
            Map<String, List<CharacterParamInfoVo>> groupByDeviceId = characterParamInfoVos.stream().collect(Collectors.groupingBy(item -> item.getDeviceId()));
            //根据不同机组获取结果。如果是全场就依次获取
            for (String key : groupByDeviceId.keySet()) {
                Long lastTime = OpentsdbOkHttpClient.queryLast(groupByDeviceId.get(key));
                QueryResponse response = iCharacterParamService
                        .getRealTimeDataByKksCode(groupByDeviceId.get(key).stream().map(item -> item.getKksCode()).collect(Collectors.toList()), (lastTime - 1) + "", lastTime + "", "");
                queryResults.addAll(response.getResults());
                xAxis = response.getResults().get(0).getDps().keySet().stream().map(item -> item.toString()).collect(Collectors.toList());
            }
            //组装数据
            Map<String, DataPower> map = new HashMap<>();
            //首页和其他页面汇总数据区分展示
            String[] strings = new String[]{};

            if ("total".equals(deviceId)) {
                strings = new String[]{
                        "定子A相电流",
                        "定子B相电流",
                        "定子C相电流",
                };
            } else {
                strings = new String[]{
                        "定子CA线电压",
                        "定子AB线电压",
                        "定子CB线电压",
                        "定子A相电流",
                        "定子B相电流",
                        "定子C相电流",
                };
            }
            for (QueryResult queryResult : queryResults) {
                DataPower.PowerPoints powerPoints = new DataPower.PowerPoints();
                powerPoints.setKksCode(queryResult.getMetric());
                powerPoints.setName(KKsCodes.get(queryResult.getMetric()));
                powerPoints.setCpunit(KKsCodes_cunit.get(queryResult.getMetric()));

                List<String> finalList = new ArrayList<>();
                queryResult.getDps().values().stream().forEach(item -> {
                    finalList.add(item.toString());
                });
                powerPoints.setValue(finalList);

                if (IS_CONTAINS(KKsCodes.get(queryResult.getMetric()), strings)) {
                    //右上图
                    //添加量程
                    powerPoints.setMeasuer(characterParamInfoVos.stream().filter(item -> item.getKksCode().equals(queryResult.getMetric())).findFirst().get().getMeasuringrangerulemaxvalue());
                    DataPower dataPower = map.getOrDefault("rightTop", new DataPower());
                    dataPower.setXAxis(xAxis);
                    dataPower.getDataList().add(powerPoints);
                    map.putIfAbsent("rightTop", dataPower);
                }
                if (IS_CONTAINS(KKsCodes.get(queryResult.getMetric()), new String[]{
                        "汽端轴振X",
                        "汽端轴振Y",
                        "励端轴振X",
                        "励端轴振Y",
                })) {
                    //右上图
                    DataPower dataPower = map.getOrDefault("rightMiddle", new DataPower());
                    dataPower.setXAxis(xAxis);
                    dataPower.getDataList().add(powerPoints);
                    map.putIfAbsent("rightMiddle", dataPower);
                }
                if (IS_CONTAINS(KKsCodes.get(queryResult.getMetric()), new String[]{
                        "汽端轴瓦温度1",
                        "励端轴瓦温度1",
                        "集电环轴瓦温度1",
                })) {
                    //右上图
                    DataPower dataPower = map.getOrDefault("rightBottom", new DataPower());
                    dataPower.setXAxis(xAxis);
                    dataPower.getDataList().add(powerPoints);
                    map.putIfAbsent("rightBottom", dataPower);
                }
                if (!"total".equals(deviceId)) {
                    if (IS_CONTAINS(KKsCodes.get(queryResult.getMetric()), new String[]{
                            //左下极坐标
                            "层间温度",
                    })) {
                        //左下图
                        DataPower dataPower = map.getOrDefault("leftBottom1", new DataPower());
                        dataPower.setXAxis(xAxis);
                        dataPower.getDataList().add(powerPoints);
                        map.putIfAbsent("leftBottom1", dataPower);
                    }
                    if (IS_CONTAINS(KKsCodes.get(queryResult.getMetric()), new String[]{
                            //左下极坐标
                            "下层线圈出水温度",
                    })) {
                        //左下图
                        DataPower dataPower = map.getOrDefault("leftBottom2", new DataPower());
                        dataPower.setXAxis(xAxis);
                        dataPower.getDataList().add(powerPoints);

                        map.putIfAbsent("leftBottom2", dataPower);
                    }
                    if (IS_CONTAINS(KKsCodes.get(queryResult.getMetric()), new String[]{
                            //左下极坐标
                            "上层线圈出水温度",
                    })) {
                        //左下图
                        DataPower dataPower = map.getOrDefault("leftBottom3", new DataPower());
                        dataPower.setXAxis(xAxis);
                        dataPower.getDataList().add(powerPoints);

                        map.putIfAbsent("leftBottom3", dataPower);
                    }

                    if (IS_CONTAINS(KKsCodes.get(queryResult.getMetric()), new String[]{
                            "有功功率",
                    })) {
                        DataPower dataPower = map.getOrDefault("有功", new DataPower());
                        dataPower.setXAxis(xAxis);
                        dataPower.getDataList().add(powerPoints);

                        map.putIfAbsent("有功", dataPower);
                    }

                    if (IS_CONTAINS(KKsCodes.get(queryResult.getMetric()), new String[]{
                            "转速1",
                    })) {
                        DataPower dataPower = map.getOrDefault("转速", new DataPower());
                        dataPower.setXAxis(xAxis);
                        dataPower.getDataList().add(powerPoints);

                        map.putIfAbsent("转速", dataPower);
                    }
                }

            }
            if ("total".equals(deviceId)) {
                //添加报警点
                DataPower dataPower4 = new DataPower();
                List<EventInfoServiceImpl.AlertCount> alertCounts = iEventInfoService.countAlert();
                DataPower.PowerPoints powerPoints = new DataPower.PowerPoints();
                powerPoints.setName("预报警");
                DataPower.PowerPoints powerPoints1 = new DataPower.PowerPoints();
                powerPoints1.setName("高报警");
                DataPower.PowerPoints powerPoints2 = new DataPower.PowerPoints();
                powerPoints2.setName("高高报警");
                DataPower.PowerPoints powerPoints3 = new DataPower.PowerPoints();
                powerPoints3.setName("趋势报警");
                dataPower4.getDataList().add(powerPoints);
                dataPower4.getDataList().add(powerPoints1);
                dataPower4.getDataList().add(powerPoints2);
                dataPower4.getDataList().add(powerPoints3);
                if (!CollectionUtil.isEmpty(alertCounts)) {
                    //获取设备长度
                    Set<String> deviceNames = new TreeSet<>();
                    alertCounts.forEach(arg -> deviceNames.add(arg.getDeviceName()));
                    int idx = 0;

                    for (String deviceName : deviceNames) {
                        dataPower4.getXAxis().add(deviceName);
                        int finalIdx = idx;
                        //最多不超过30条
                        Random r1 = new Random();
                        alertCounts.forEach(arg -> {
                            if (deviceName.equals("1号机组")) {
                                //处理名字报警
                                if ("preAlert".equals(arg.getAlertLevel())) {
                                    //预报警
                                    dataPower4.getDataList().get(0).getValue().add(arg.getCount() > 30L ? "12" : (arg.getCount() + ""));
                                } else if ("tallAlert".equals(arg.getAlertLevel())) {
                                    //高报
                                    dataPower4.getDataList().get(1).getValue().add(arg.getCount() > 30L ? "15" : (arg.getCount() + ""));
                                } else if ("tooTallAlert".equals(arg.getAlertLevel())) {
                                    //高高报
                                    dataPower4.getDataList().get(2).getValue().add(arg.getCount() > 30L ? "20" : (arg.getCount() + ""));
                                } else {
                                    dataPower4.getDataList().get(3).getValue().add(arg.getCount() > 30L ? "2" : (arg.getCount() + ""));
                                }
                            }
                            if (deviceName.equals("2号机组")) {
                                //处理名字报警
                                if ("preAlert".equals(arg.getAlertLevel())) {
                                    //预报警
                                    dataPower4.getDataList().get(0).getValue().add(arg.getCount() > 30L ? "22" : (arg.getCount() + ""));
                                } else if ("tallAlert".equals(arg.getAlertLevel())) {
                                    //高报
                                    dataPower4.getDataList().get(1).getValue().add(arg.getCount() > 30L ? "18" : (arg.getCount() + ""));
                                } else if ("tooTallAlert".equals(arg.getAlertLevel())) {
                                    //高高报
                                    dataPower4.getDataList().get(2).getValue().add(arg.getCount() > 30L ? "30" : (arg.getCount() + ""));
                                } else {
                                    dataPower4.getDataList().get(3).getValue().add(arg.getCount() > 30L ? "4" : (arg.getCount() + ""));
                                }
                            }
                        });
                    }

                    idx++;
                }
                map.put("alert", dataPower4);
            }
            try {
                List<Map.Entry<String, String>> deviceGroupMap = groupMap.get(deviceId);
                //根据deviceid统一发送
                for (Map.Entry<String, String> entry : deviceGroupMap) {
                    final SendWebSocket webSocket = webSocketMap.get(entry.getKey());
                    webSocket.sendMessage(JSON.toJSONString(map));
                }
            } catch (
                    IOException e) {
                e.printStackTrace();
            }
        }
    }
}
