package com.gyee.wisdom.alarm.sharding.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.gyee.wisdom.alarm.sharding.cache.*;
import com.gyee.wisdom.alarm.sharding.entity.*;
import com.gyee.wisdom.alarm.sharding.mapper.*;
import com.gyee.wisdom.alarm.sharding.model.TreeNode;
import com.gyee.wisdom.alarm.sharding.util.SnowflakeGenerator;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * 设备管理相关数据服务
 */
@Service
@Slf4j
public class DeviceService {

    @Autowired
    private DeviceMapper deviceMapper;

    @Autowired
    private DeviceStructureMapper deviceStructureMapper;

    @Autowired
    private DeviceMetricsMapper deviceMetricsMapper;

    @Autowired
    private DeviceModelMapper deviceModelMapper;

    @Autowired
    private DeviceModelMetricsMapper deviceModelMetricsMapper;

    @Autowired
    private TestingPointAIMapper testingPointAIMapper;

    @Autowired
    private TestingPointDIMapper testingPointDIMapper;

    @Autowired
    private WindTurbineTestingPointDiMapper windTurbineTestingPointDiMapper;

    @Autowired
    private WindTurbineTestingPointAiMapper windTurbineTestingPointAiMapper;

    @Autowired
    private WindturbineCache windturbineCache;

    @Autowired
    private PointUnitCache pointUnitCache;

    public List<Device> getAllDevice() {
        return deviceMapper.getAll();
    }

    public List<DeviceStructure> getAllDeviceStructure() {
        return deviceStructureMapper.getAllDeviceStructure();
    }


    public List<DeviceStructure> getDeviceStructureByDeviceId(String deviceId) {
        return deviceStructureMapper.getDeviceStructureByDeviceId(deviceId);
    }

    public List<DeviceStructure> getDeviceStructureChildNode(String deviceId, String nodeCode) {
        return deviceStructureMapper.getDeviceStructureChildNode(deviceId, nodeCode);
    }

    public DeviceStructure getDeviceStructureByCode(String deviceId, String nodeCode) {
        return deviceStructureMapper.getDeviceStructureByCode(deviceId, nodeCode);
    }

    public TreeNode<DeviceStructure> getDeviceStructureTree(String deviceId) {

        if (CacheService.deviceStructureMap == null) {
            CacheService.deviceStructureMap = new HashMap<>();
        }

        if (CacheService.deviceStructureMap.containsKey(deviceId))
            return CacheService.deviceStructureMap.get(deviceId);

        List<DeviceStructure> lst = deviceStructureMapper.getDeviceStructureChildNode(deviceId, "0");
        if (lst != null && lst.size() > 0) {
            DeviceStructure ds = lst.get(0);
            TreeNode<DeviceStructure> treeNode = getSubDeviceStructureTreeNode(ds);
            CacheService.deviceStructureMap.put(ds.getDeviceid(), treeNode);
            return treeNode;
        }

        return null;
    }

    public TreeNode<DeviceStructure> getDeviceStructureTree(String deviceId, String nodeCode) {

        DeviceStructure ds = deviceStructureMapper.getDeviceStructureByCode(deviceId, nodeCode);
        return getSubDeviceStructureTreeNode(ds);
    }

    private TreeNode<DeviceStructure> getSubDeviceStructureTreeNode(DeviceStructure ds) {

        TreeNode<DeviceStructure> rootNode = new TreeNode<>();
        if (ds == null)
            return rootNode;
        rootNode.setNode(ds);

        List<DeviceStructure> dsList = deviceStructureMapper.getDeviceStructureChildNode(ds.getDeviceid(), ds.getCode());
        if (dsList != null && dsList.size() > 0) {
            List<TreeNode> children = new ArrayList<>();
            for (DeviceStructure ds1 : dsList) {
                children.add(getSubDeviceStructureTreeNode(ds1));
            }
            rootNode.setChildren(children);
        }

        return rootNode;

    }

    public int deleteDeviceStructure(long dsId) {
        int code = deviceStructureMapper.deleteById(dsId);
        if (code >= 1) {
            //树结构变化清空树结构缓存
            CacheService.deviceStructureMap.clear();
        }
        return code;
    }

    public int saveOrUpdateDeviceStructure(DeviceStructure ds) {
        int result = 0;
        if (ds.getId() <= 0) {
            //如果id为空，则通过雪花算法 生成一个id
            ds.setId(SnowflakeGenerator.generateId());
            result = deviceStructureMapper.insert(ds);
        } else {
            DeviceStructure oldData = deviceStructureMapper.selectById(ds.getId());
            if (oldData != null) {
                result = deviceStructureMapper.updateById(ds);
            } else {
                result = deviceStructureMapper.insert(ds);
            }
        }
        //树结构变化清空树结构缓存
        CacheService.deviceStructureMap.clear();
        return result;

    }

    public List<DeviceMetrics> getDeviceMetricsByDeviceId(String deviceId) {
        return deviceMetricsMapper.getDeviceMetricsByDeviceId(deviceId);
    }

    public List<DeviceMetrics> getDeviceMetricsByStructureCode(String deviceId, String structureCode) {
        return deviceMetricsMapper.getDeviceMetricsByStructureCode(deviceId, structureCode);
    }

    public DeviceMetrics getDeviceMetricsByCode(String deviceId, String metricCode) {
        return deviceMetricsMapper.getDeviceMetricsByCode(deviceId, metricCode);
    }

    public int deleteDeviceMetric(long metricId) {
        return deviceMetricsMapper.deleteById(metricId);
    }

    public int saveOrUpdateDeviceMetric(DeviceMetrics metrics, List<DeviceModelMetrics> deviceModelMetrics) {

        int result = 0;
        if (metrics.getId() <= 0) {
            //如果id为空，则通过雪花算法 生成一个id
            metrics.setId(SnowflakeGenerator.generateId());
            result = deviceMetricsMapper.insertByMetrics(metrics);
        } else {
            DeviceMetrics oldData = deviceMetricsMapper.selectByMetricsId(metrics.getId());
            if (oldData != null) {
                result = deviceMetricsMapper.updateByMetricsId(metrics);
            } else {
                result = deviceMetricsMapper.insertByMetrics(metrics);
            }
        }
        if (deviceModelMetrics != null && deviceModelMetrics.size() > 0) {
            for (DeviceModelMetrics deviceModelMetrics1 : deviceModelMetrics) {
                if (deviceModelMetrics1.getId() <= 0) {
                    //如果id为空，则通过雪花算法 生成一个id
                    deviceModelMetrics1.setId((int) SnowflakeGenerator.generateId());
                    result = deviceModelMetricsMapper.insertModelMetrics(deviceModelMetrics1);
                } else {
                    DeviceModelMetrics deviceModelMetrics2 = deviceModelMetricsMapper.selectModelMetricsById(deviceModelMetrics1.getId());
                    if (deviceModelMetrics2 != null) {
                        result = deviceModelMetricsMapper.updateModelMetricsById(deviceModelMetrics1);
                    } else {
                        result = deviceModelMetricsMapper.insertModelMetrics(deviceModelMetrics1);
                    }
                }
            }
        }

        return result;

    }


    public List<DeviceModel> getDeviceModelsById(String id) {
        return deviceModelMapper.getDeviceModelsById(id);
    }

    public int deleteDeviceModel(int id) {
        return deviceModelMapper.deleteById(id);
    }

    public DeviceModel getDeviceModelByCode(String deviceid, String code) {
        return deviceModelMapper.getDeviceModelByCode(deviceid, code);
    }

    public int saveOrUpdateDeviceModel(DeviceModel deviceModel) {
        int result = 0;
        if (deviceModel.getId() <= 0) {
            //如果id为空，则通过雪花算法 生成一个id
            deviceModel.setId((int) SnowflakeGenerator.generateId());
            result = deviceModelMapper.insert(deviceModel);
        } else {
            DeviceModel oldData = deviceModelMapper.selectById(deviceModel.getId());
            if (oldData != null) {
                result = deviceModelMapper.updateById(deviceModel);
            } else {
                result = deviceModelMapper.insert(deviceModel);
            }
        }

        return result;
    }

    public List<DeviceModel> getDeviceModelList() {
        return deviceModelMapper.getAll();
    }

    public List<DeviceModelMetrics> getDeviceModelMetricsList() {
        return deviceModelMetricsMapper.getAll();
    }

    public IPage<DeviceMetrics> pageQueryAll(Page page, String deviceId,String categorydata,String keyword,String model, String structureCode) {
        return deviceMetricsMapper.pageQueryAll(page, deviceId,categorydata,keyword,model, structureCode);
    }

    public int insertOrUpdate(List<DeviceMetrics> deviceMetrics) {
        int s = 0;
        for (DeviceMetrics deviceMetrics1 : deviceMetrics) {
            DeviceMetrics deviceMetrics2 = deviceMetricsMapper.selectByMetriccode(deviceMetrics1.getMetriccode());
            if (deviceMetrics2 != null) {
                deviceMetrics1.setId(deviceMetrics2.getId());
                s = deviceMetricsMapper.updateByMetricsId(deviceMetrics1);
            } else {
                deviceMetrics1.setDeviceid("windturbine");
                deviceMetrics1.setId(SnowflakeGenerator.generateId());
                s = deviceMetricsMapper.insertByMetrics(deviceMetrics1);
            }
        }
        return s;
    }

    public JSONObject getTestingPointByStructCode(String deviceId, String structCode, String windturbineId, int pageSize, int pageNum) {
        JSONObject resultObject = new JSONObject();
        List<JSONObject> jsonArrayList = new ArrayList<>();
        String modelId = "";
        Windturbine windturbine = windturbineCache.getWindturbine(windturbineId);
        if (windturbine != null)
            modelId = windturbine.getModelid();

        if (StringUtils.isNotBlank(structCode)) {
            List<DeviceMetrics> metricsList = deviceMetricsMapper.getDeviceMetricsByStructureCode(deviceId, structCode);

            List<String> collect = metricsList.stream().map(s -> s.getMetriccode()).collect(Collectors.toList());

            if (collect.size() > 0) {
                List<DeviceModelMetrics> deviceModelMetricsList = deviceModelMetricsMapper.getDeviceModelMetrics(collect, modelId);
                List<String> uniformcodeList = deviceModelMetricsList.stream().map(s -> s.getUniformcode()).collect(Collectors.toList());

                List<String> uniformcodeList_AI = uniformcodeList.stream().filter(s -> s.toUpperCase().contains("AI")).collect(Collectors.toList());
                List<String> uniformcodeList_DI = uniformcodeList.stream().filter(s -> s.toUpperCase().contains("DI")).collect(Collectors.toList());

                List<WindTurbineTestingPointAi> testingPointAIS = new ArrayList<>();
                if (uniformcodeList_AI.size() > 0)
                    testingPointAIS = windTurbineTestingPointAiMapper.getPointList(windturbineId, uniformcodeList_AI);
                List<WindTurbineTestingPointDi> testingPointDIS = new ArrayList<>();
                if (uniformcodeList_DI.size() > 0)
                    testingPointDIS = windTurbineTestingPointDiMapper.getPointList(windturbineId, uniformcodeList_DI);

                Map<String, DeviceMetrics> mapByModel = pointUnitCache.getMapByModel(modelId);

                List<JSONObject> array_ai = new ArrayList<>();
                List<JSONObject> array_di = new ArrayList<>();
                for (WindTurbineTestingPointAi ai :
                        testingPointAIS) {

                    if(ai.getUniformcode()==null||!ai.getUniformcode().toUpperCase().startsWith("AI"))
                        continue;
                    JSONObject obj = new JSONObject();

                    obj.put("englishName", ai.getEnglishname());
                    obj.put("modelId", ai.getModelid());
                    obj.put("name", ai.getName());
                    obj.put("valueUnit", ai.getValueunit());
                    obj.put("model", ai.getModel());
                    obj.put("typeId", ai.getTypeid());
                    obj.put("id", ai.getId());
                    obj.put("uniformCode", ai.getUniformcode());


                    String unitName = "";
                    String unitNameCn = "";
                    if (mapByModel != null) {
                        if (mapByModel.containsKey(ai.getUniformcode())) {
                            unitName = mapByModel.get(ai.getUniformcode()).getUnitname();
                            unitNameCn = mapByModel.get(ai.getUniformcode()).getUnitnamecn();
                        }
                    }
                    obj.put("unitName", unitName);
                    obj.put("unitNameCn", unitNameCn);
                    array_ai.add(obj);

                }

                for (WindTurbineTestingPointDi di :
                        testingPointDIS) {
                    if(di.getUniformcode()==null||!di.getUniformcode().toUpperCase().startsWith("DI"))
                        continue;
                    JSONObject obj = new JSONObject();

                    obj.put("englishName", di.getEnglishName());
                    obj.put("modelId", di.getModelId());
                    obj.put("name", di.getName());
                    obj.put("valueUnit", di.getValueunit());
                    obj.put("model", di.getModel());
                    obj.put("typeId", di.getTypeId());
                    obj.put("id", di.getId());
                    obj.put("uniformCode", di.getUniformcode());
                    String unitName = "";
                    String unitNameCn = "";
                    if (mapByModel != null) {
                        if (mapByModel.containsKey(di.getUniformcode())) {
                            unitName = mapByModel.get(di.getUniformcode()).getUnitname();
                            unitNameCn = mapByModel.get(di.getUniformcode()).getUnitnamecn();
                        }
                    }
                    obj.put("unitName", unitName);
                    obj.put("unitNameCn", unitNameCn);
                    array_di.add(obj);

                }

                jsonArrayList.addAll(array_ai);
                jsonArrayList.addAll(array_di);

                List<List<JSONObject>> partition = Lists.partition(jsonArrayList, pageSize);

                if (partition.size() > 0)
                    resultObject.put("records", partition.get(pageNum - 1));
                else
                    resultObject.put("records", new ArrayList<>());
                resultObject.put("total", jsonArrayList.size());
                resultObject.put("pages", partition.size());
                resultObject.put("current", pageNum);

            }
        } else {

            List<WindTurbineTestingPointAi> aiPointList = windTurbineTestingPointAiMapper.getPointList(windturbineId, new ArrayList<>());
            List<WindTurbineTestingPointDi> diPointList = windTurbineTestingPointDiMapper.getPointList(windturbineId, new ArrayList<>());

            Map<String, DeviceMetrics> mapByModel = pointUnitCache.getMapByModel(modelId);

            List<JSONObject> array_ai = new ArrayList<>();
            List<JSONObject> array_di = new ArrayList<>();
            for (WindTurbineTestingPointAi ai :
                    aiPointList) {
                if(ai.getUniformcode()==null||!ai.getUniformcode().toUpperCase().startsWith("AI"))
                    continue;
                JSONObject obj = new JSONObject();
                obj.put("englishName", ai.getEnglishname());
                obj.put("modelId", ai.getModelid());
                obj.put("name", ai.getName());
                obj.put("valueUnit", ai.getValueunit());
                obj.put("model", ai.getModel());
                obj.put("typeId", ai.getTypeid());
                obj.put("id", ai.getId());
                obj.put("uniformCode", ai.getUniformcode());
                String unitName = "";
                String unitNameCn = "";
                if (mapByModel != null) {
                    if (mapByModel.containsKey(ai.getUniformcode())) {
                        unitName = mapByModel.get(ai.getUniformcode()).getUnitname();
                        unitNameCn = mapByModel.get(ai.getUniformcode()).getUnitnamecn();
                    }
                }

                obj.put("unitName", unitName);
                obj.put("unitNameCn", unitNameCn);
                array_ai.add(obj);

            }

            for (WindTurbineTestingPointDi di :
                    diPointList) {
                if(di.getUniformcode()==null||!di.getUniformcode().toUpperCase().startsWith("DI"))
                    continue;
                JSONObject obj = new JSONObject();
                obj.put("englishName", di.getEnglishName());
                obj.put("modelId", di.getModelId());
                obj.put("name", di.getName());
                obj.put("valueUnit", di.getValueunit());
                obj.put("model", di.getModel());
                obj.put("typeId", di.getTypeId());
                obj.put("id", di.getId());
                obj.put("uniformCode", di.getUniformcode());

                String unitName = "";
                String unitNameCn = "";
                if (mapByModel != null) {
                    if (mapByModel.containsKey(di.getUniformcode())) {
                        unitName = mapByModel.get(di.getUniformcode()).getUnitname();
                        unitNameCn = mapByModel.get(di.getUniformcode()).getUnitnamecn();
                    }
                }

                obj.put("unitName", unitName);
                obj.put("unitNameCn", unitNameCn);
                array_di.add(obj);

            }
            jsonArrayList.addAll(array_ai);
            jsonArrayList.addAll(array_di);

            List<List<JSONObject>> partition = Lists.partition(jsonArrayList, pageSize);

            if (partition.size() > 0)
                resultObject.put("records", partition.get(pageNum - 1));
            else
                resultObject.put("records", new ArrayList<>());
            resultObject.put("total", jsonArrayList.size());
            resultObject.put("pages", partition.size());
            resultObject.put("current", pageNum);
        }
        return resultObject;


    }

}
