package com.gyee.dataadapter.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.gyee.dataadapter.dao.IHistoryDao;
import com.gyee.dataadapter.dao.ILatestDao;
import com.gyee.dataadapter.entity.PointData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
public class TsDataService {

    @Resource
    private IAdapterService adapterService;
    @Resource
    private ILatestDao latestDao;
    @Resource
    private IHistoryDao historyDao;

    public Map<String, PointData> getLatest(String tagNames) {
        String[] split = tagNames.split(",");
        return getLatest(Arrays.asList(split));
    }

    public Map<String, PointData> getLatest(List<String> tagNames) {
        Map<String, PointData> latest = new HashMap<>();
        if(CollUtil.isEmpty(tagNames)) return latest;
        Map<Boolean, List<String>> nxFgs = tagNames.stream().collect(Collectors.groupingBy(tn -> tn.startsWith("NX")));
        try {
            latest = historyDao.getLatest(nxFgs.get(true));
        } catch (Exception e) {
            e.printStackTrace();
        }
        List<String> strings = nxFgs.get(false);
        Map<String, PointData> data2 = adapterService.getLatestData2(strings);
        List<String> strings2 = new ArrayList<>();
        if(strings != null){
            for (String string : strings) {
                if(!data2.containsKey(string)){
                    strings2.add(string);
                }
            }
        }
        if(!strings2.isEmpty()){
            int k=1;
            Map<String, PointData> dataMap;
            do{
                dataMap = getHistorySection(new Date(), strings2.stream().collect(Collectors.joining(",")),k*12);
                k++;
            }while (k<20 && dataMap.isEmpty());
            latest.putAll(dataMap);
        }
        latest.putAll(data2);
        return latest;
    }

    public List<PointData> getHistoryRaw(String tagName, Date startTime, Date endTime) {
        try {
            if (tagName.startsWith("NX")) {
                return historyDao.getHistoryRaw(tagName, startTime, endTime);
            } else {
                startTime = DateUtil.offsetHour(startTime, -8);
                endTime = DateUtil.offsetHour(endTime, -8);
                return adapterService.getPointData(startTime, endTime, 1, null, tagName);
            }
        } catch (Exception e) {
            log.error("异常点：" + tagName);
            log.error(e.getMessage());
            return new ArrayList<>();
        }
    }

    public List<PointData> getHistoryRaw(String tagName, long startTs, long endTs) {
        return getHistoryRaw(tagName, new Date(startTs), new Date(endTs));
    }

    public List<PointData> getHistorySnap(String tagName, long startTs, long endTs, Integer interval) {
        return getHistorySnap(tagName, new Date(startTs), new Date(endTs), interval);
    }

    public List<PointData> getHistorySnap(String tagName, Date startTime, Date endTime, Integer interval) {
        if (interval == null || interval == 0) interval = 60;
        try {
            if (tagName.startsWith("NX")) {
                return historyDao.getHistorySnap(tagName, startTime, endTime, interval);
            } else {
                return adapterService.getPointData(startTime, endTime, 0, interval, tagName);
            }
        } catch (Exception e) {
            log.error("异常点：" + tagName);
            log.error(e.getMessage());
            return new ArrayList<>();
        }
    }

    /**
     * @param startTime：开始时间。
     * @param endTime：结束时间。
     * @param type：采样类型。0瞬时值，1原始值，2最大值，3最小值，4平均值。
     * @param interval：采样频率，单位秒。
     * @param tagName：要查询的变量（数据、测点）名。
     */
    public List<PointData> getHistoryStat(String tagName, Date startTime, Date endTime, Integer interval, Integer type) {
        if (interval == null || interval == 0) interval = 60;
        if (type == null || type < 2 || type > 4) type = 4;
        try {
            if (tagName.startsWith("NX") || tagName.startsWith("NXFGS_")) {
                return historyDao.getHistoryStat(tagName, startTime, endTime, interval, type);
            } else {
                return adapterService.getPointData(startTime, endTime, type, interval, tagName);
            }
        } catch (Exception e) {
            log.error("异常点：" + tagName);
            log.error(e.getMessage());
            return new ArrayList<>();
        }
    }


    public List<PointData> getHistoryStat2(String tagName, Date startTime, Date endTime, Integer type) {
        if (type == null || type < 2 || type > 4) type = 4;
        try {
            if (tagName.startsWith("NX") || tagName.startsWith("NXFGS_")) {
                return historyDao.getHistoryStat2(tagName, startTime, endTime, type);
            } else {
                return adapterService.getPointData2(startTime, endTime, type, tagName);
            }
        } catch (Exception e) {
            log.error("异常点：" + tagName);
            log.error(e.getMessage());
            return new ArrayList<>();
        }
    }

    public PointData getHistoryStat0(String tagName, Date startTime, Date endTime, Integer type) {
        if (tagName.startsWith("NX")) {
            try {
                return historyDao.getHistoryStat0(tagName, startTime, endTime, type);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            int interval = (int) TimeUnit.MILLISECONDS.toMinutes(endTime.getTime() - startTime.getTime());
            List<PointData> pd = adapterService.getPointData(startTime, endTime, type, interval, tagName);
            return pd.get(0);
        }
        return new PointData();
    }

    public boolean writeLatest(List<PointData> dataList) {
        return latestDao.writeLatest(dataList);
    }

    public boolean writeLatest(PointData data) {
        return writeLatest(Collections.singletonList(data));
    }

    public Map<String, PointData> getHistorySection(long ts, String tagNames) {
        return getHistorySection(new Date(ts), tagNames);
    }

    public Map<String, PointData> getHistorySection(Date time, String tagNames) {
        Map<String, PointData> result = new HashMap<>();
        if(StrUtil.isBlank(tagNames)) return result;
        Map<Boolean, List<String>> nxFgs = Arrays.stream(tagNames.split(",")).collect(
                Collectors.groupingBy(tn -> tn.toUpperCase().startsWith("NX")));
        try {
            Map<String, PointData> latest = historyDao.getHistorySection(time, nxFgs.get(true));
            result.putAll(latest);
            List<String> strings = nxFgs.get(false);
            if (CollUtil.isEmpty(strings)) return result;
            for (String tagName : strings) {
                //Date start, Date end, Integer sampleType, Integer sampleRate, String paths,
                //                                String pageIndex, String pageSize, Boolean isDesc
                DateTime time0 = DateUtil.offsetHour(time, -3);
                List<PointData> pdsMap = adapterService.getPointData(time0, time, 0, 600, tagName,"1","1",true);
                if (CollUtil.isNotEmpty(pdsMap)) result.put(tagName, pdsMap.get(0));
            }
            return result;
        } catch (Exception e) {
            log.error("Section");
            log.error(e.getMessage());
            return new HashMap<>();
        }
    }

    public Map<String, PointData> getHistorySection(Date time, String tagNames,int hour) {
        Map<String, PointData> result = new HashMap<>();
        if(StrUtil.isBlank(tagNames)) return result;
        Map<Boolean, List<String>> nxFgs = Arrays.stream(tagNames.split(",")).collect(
                Collectors.groupingBy(tn -> tn.toUpperCase().startsWith("NX")));
        try {
            Map<String, PointData> latest = historyDao.getHistorySection(time, nxFgs.get(true));
            result.putAll(latest);
            List<String> strings = nxFgs.get(false);
            if (CollUtil.isEmpty(strings)) return result;
            for (String tagName : strings) {
                //Date start, Date end, Integer sampleType, Integer sampleRate, String paths,
                //                                String pageIndex, String pageSize, Boolean isDesc
                DateTime time0 = DateUtil.offsetHour(time, -hour);
                List<PointData> pdsMap = adapterService.getPointData(time0, time, 0, 600, tagName,"1","1",true);
                if (CollUtil.isNotEmpty(pdsMap)) result.put(tagName, pdsMap.get(0));
            }
            return result;
        } catch (Exception e) {
            log.error("Section");
            log.error(e.getMessage());
            return new HashMap<>();
        }
    }
}
