package com.gyee.wisdom.dao.golden;

import com.gyee.wisdom.common.data.timeseries.*;
import com.gyee.wisdom.common.exception.WisdomException;
import com.gyee.wisdom.dao.timeseries.GoldenDao;
import com.gyee.wisdom.dao.timeseries.IDataChangeDao;
import com.gyee.wisdom.dao.timeseries.ILatestDao;
import com.rtdb.enums.Quality;
import com.rtdb.model.*;
import com.rtdb.service.impl.BaseImpl;
import com.rtdb.service.impl.ServerImpl;
import com.rtdb.service.impl.SnapshotImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

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

@Component
@GoldenDao
@Slf4j
public class GoldenDataChangeDao implements IDataChangeDao {

    @Autowired
    private GoldenConfig goldenConfig;

    private HashMap<String, HashMap<TsDataType, CacheData>> topicMap;

    public void registerTopic(String topic, List<TsPoint> tsPoints)  {
        if (topicMap == null) {
            topicMap = new HashMap<>();
        }
        HashMap<TsDataType, CacheData> tsDataTypeHashMap;
        if (topicMap.containsKey(topic)) {
            tsDataTypeHashMap =  topicMap.get(topic);
            tsDataTypeHashMap.clear();
        } else {
            tsDataTypeHashMap = new HashMap<>();
        }

        ServerImpl connection = null;
        try {
            connection = goldenConfig.getGoldenConnectionPool().getConnection();
            BaseImpl base = new BaseImpl(connection);
            Map<TsDataType, List<TsPoint>> pointGroup = tsPoints.stream().collect(Collectors.groupingBy(TsPoint::getTsDataType));
            for (Map.Entry<TsDataType, List<TsPoint>> entry : pointGroup.entrySet()) {
                String[] tagNames = entry.getValue().stream().map(TsPoint::getId).toArray(String[]::new);
                List<MinPoint> lstPoint = base.findPoints(tagNames);
                int[] ids = lstPoint.stream().mapToInt(MinPoint::getId).toArray();

                tsDataTypeHashMap.put(entry.getKey(), new CacheData(tagNames, ids));
            }

            if (topicMap.containsKey(topic) == false)
                topicMap.put(topic, tsDataTypeHashMap);
        } catch (Exception ex) {
            log.error(ex.getMessage());
        } finally {
            if (connection != null)
                this.goldenConfig.getGoldenConnectionPool().returnConnection(connection);
        }

    }

    public void unRegisterTopic(String topic) {
        if (topicMap != null && topicMap.containsKey(topic)) {
            topicMap.remove(topic);
        }
    }

    public Map<String, TsData> getTopicDataChange(String topic) {
        if (topicMap == null || topicMap.containsKey(topic) == false)
            return null;

        try {
            Map<String, TsData> result = new HashMap<>();
            HashMap<TsDataType, CacheData> tsDataTypeHashMap = topicMap.get(topic);
            for (Map.Entry<TsDataType, CacheData> entry : tsDataTypeHashMap.entrySet()) {
                int[] tagIds = entry.getValue().getIds();
                //String[] tagNames = entry.getValue().getTagNames();
                if (entry.getKey() == TsDataType.DOUBLE) {
                    result.putAll(getDoubleTsDataChanges(topic, tagIds));
                } else if (entry.getKey() == TsDataType.LONG) {
                    result.putAll(getLongTsDataChanges(topic, tagIds));
                } else if (entry.getKey() == TsDataType.BOOLEAN) {
                    result.putAll(getBooleanTsDataChanges(topic, tagIds));
                }  else {
                    throw new WisdomException("不支持数据类型:" + entry.getKey());
                }
            }

            return result;
        } catch (Exception ex) {
            log.error(ex.getMessage());
            return  null;
        }
    }

    private Map<String, TsData> getDoubleTsDataChanges(String topic, int[] tagIds) throws Exception {
        ServerImpl connection = null;
        try {
            connection = goldenConfig.getGoldenConnectionPool().getConnection();
            SnapshotImpl snap = new SnapshotImpl(connection);
            CacheData cacheData = topicMap.get(topic).get(TsDataType.DOUBLE);
            Entity<DoubleData> entityD = snap.getDoubleSnapshots(tagIds);
            Map<String, TsData> tsDataMap = new HashMap<>();
            for (int i = 0; i < tagIds.length; i++) {
                if (cacheData.getData()[i] == null || cacheData.getData()[i].getDoubleValue().isPresent() == false) {
                    cacheData.getData()[i] = new GeneralTsData();
                    cacheData.getData()[i].setTs(entityD.getList().get(i).getDateTime().getTime());
                    cacheData.getData()[i].setDoubleValue(Optional.of(entityD.getList().get(i).getValue()));
                    //暂注释，解决首次订阅，立即给客户端推送订阅点的值  wanghs 20180813
                   /* tsDataMap.put(cacheData.getTagNames()[i],
                            new DoubleTsData(entityD.getList().get(i).getDateTime().getTime(),
                                    entityD.getList().get(i).getQuality(),
                                    entityD.getList().get(i).getValue()));*/
                } else if (cacheData.getData()[i].getDoubleValue().get().doubleValue() != entityD.getList().get(i).getValue()) {
                    cacheData.getData()[i].setTs(entityD.getList().get(i).getDateTime().getTime());
                    cacheData.getData()[i].setDoubleValue(Optional.of(entityD.getList().get(i).getValue()));
                    tsDataMap.put(cacheData.getTagNames()[i],
                            new DoubleTsData(entityD.getList().get(i).getDateTime().getTime(),
                                    entityD.getList().get(i).getQuality(),
                                    entityD.getList().get(i).getValue()));
                }
            }
            return tsDataMap;
        } finally {
            if (connection != null)
                this.goldenConfig.getGoldenConnectionPool().returnConnection(connection);
        }
    }

    private Map<String, TsData> getLongTsDataChanges(String topic, int[] tagIds) throws Exception {
        ServerImpl connection = null;
        try {
            connection = goldenConfig.getGoldenConnectionPool().getConnection();
            SnapshotImpl snap = new SnapshotImpl(connection);
            CacheData cacheData = topicMap.get(topic).get(TsDataType.LONG);
            Entity<IntData> entityD = snap.getIntSnapshots(tagIds);
            Map<String, TsData> tsDataMap = new HashMap<>();
            for (int i  = 0; i < tagIds.length; i++) {
                if (cacheData.getData()[i] == null || cacheData.getData()[i].getDoubleValue().isPresent() == false) {
                    cacheData.getData()[i] = new GeneralTsData();
                    cacheData.getData()[i].setTs(entityD.getList().get(i).getDateTime().getTime());
                    cacheData.getData()[i].setDoubleValue(Optional.of(entityD.getList().get(i).getValue()));
                    //暂注释，解决首次订阅，立即给客户端推送订阅点的值  wanghs 20180813
                  /*  tsDataMap.put(cacheData.getTagNames()[i],
                            new LongTsData(entityD.getList().get(i).getDateTime().getTime(),
                                    entityD.getList().get(i).getQuality(),
                                    (long)entityD.getList().get(i).getValue()));*/
                } else if (cacheData.getData()[i].getDoubleValue().get().doubleValue() != entityD.getList().get(i).getValue()) {
                    cacheData.getData()[i].setTs(entityD.getList().get(i).getDateTime().getTime());
                    cacheData.getData()[i].setDoubleValue(Optional.of(entityD.getList().get(i).getValue()));
                    tsDataMap.put(cacheData.getTagNames()[i],
                            new LongTsData(entityD.getList().get(i).getDateTime().getTime(),
                                    entityD.getList().get(i).getQuality(),
                                    (long)entityD.getList().get(i).getValue()));
                }
            }
            return tsDataMap;
        } finally {
            if (connection != null)
                this.goldenConfig.getGoldenConnectionPool().returnConnection(connection);
        }
    }

    private Map<String, TsData> getBooleanTsDataChanges(String topic, int[] tagIds) throws Exception {
        ServerImpl connection = null;
        try {
            connection = goldenConfig.getGoldenConnectionPool().getConnection();
            SnapshotImpl snap = new SnapshotImpl(connection);
            CacheData cacheData = topicMap.get(topic).get(TsDataType.BOOLEAN);
            Entity<IntData> entityD = snap.getIntSnapshots(tagIds);
            Map<String, TsData> tsDataMap = new HashMap<>();
            for (int i = 0; i < tagIds.length; i++) {
                if (cacheData.getData()[i] == null || cacheData.getData()[i].getDoubleValue().isPresent() == false) {
                    cacheData.getData()[i] = new GeneralTsData();
                    cacheData.getData()[i].setTs(entityD.getList().get(i).getDateTime().getTime());
                    cacheData.getData()[i].setDoubleValue(Optional.of(entityD.getList().get(i).getValue()));
                    //暂注释，解决首次订阅，立即给客户端推送订阅点的值  wanghs 20180813
                   /* tsDataMap.put(cacheData.getTagNames()[i],
                            new BooleanTsData(entityD.getList().get(i).getDateTime().getTime(),
                                    entityD.getList().get(i).getQuality(),
                                    entityD.getList().get(i).getValue() ==1));*/
                } else if (cacheData.getData()[i].getDoubleValue().get().doubleValue() != entityD.getList().get(i).getValue()) {
                    cacheData.getData()[i].setTs(entityD.getList().get(i).getDateTime().getTime());
                    cacheData.getData()[i].setDoubleValue(Optional.of(entityD.getList().get(i).getValue()));
                    tsDataMap.put(cacheData.getTagNames()[i],
                            new BooleanTsData(entityD.getList().get(i).getDateTime().getTime(),
                                    entityD.getList().get(i).getQuality(),
                                    entityD.getList().get(i).getValue() == 1));
                }
            }
            return tsDataMap;
        } finally {
            if (connection != null)
                this.goldenConfig.getGoldenConnectionPool().returnConnection(connection);
        }
    }


}
