package com.gyee.edge.loader.golden;

import com.gyee.edge.loader.data.TsDataType;
import com.gyee.edge.loader.data.TsPointData;
import com.gyee.edge.loader.golden.config.GoldenConfig;
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 org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

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

@Component
public class GoldenLatestDao implements ILatestDao {

    @Autowired
    private GoldenConfig goldenConfig;



    public int writeDoubleLatest(List<TsPointData> list) throws Exception {
        ServerImpl connection = null;
        try {
            connection = goldenConfig.getGoldenConnectionPool().getConnection();
            SnapshotImpl snap = new SnapshotImpl(connection);
            BaseImpl base = new BaseImpl(connection);
            String[] tagNames = list.stream().map(TsPointData::getTagName).toArray(String[]::new);
            List<MinPoint> pointList = base.findPoints(tagNames);
            List<DoubleData> doubleList = new ArrayList<>();
            for (int i = 0; i < list.size(); i++) {
                Date time = new Date();
                time.setTime(list.get(0).getTsData().getTs());
                DoubleData data = new DoubleData(pointList.get(i).getId(), time, list.get(i).getTsData().getDoubleValue().get()
                        , (short) 0, 0);
                doubleList.add(data);
            }
            int count = snap.putDoubleSnapshots(doubleList);
            return count;
        } finally {
            if (connection != null)
                goldenConfig.getGoldenConnectionPool().returnConnection(connection);
        }
    }

    @Override
    public int writeStringLatest(List<TsPointData> list) throws Exception {
        ServerImpl connection = null;
        try {
            connection = goldenConfig.getGoldenConnectionPool().getConnection();
            SnapshotImpl snap = new SnapshotImpl(connection);
            BaseImpl base = new BaseImpl(connection);
            String[] tagNames = list.stream().map(TsPointData::getTagName).toArray(String[]::new);
            List<MinPoint> pointList = base.findPoints(tagNames);
            List<BlobData> blobList = new ArrayList<>();
            for (int i = 0; i < list.size(); i++) {
                BlobData pointData = new BlobData();
                Date date = new Date();
                date.setTime(list.get(i).getTsData().getTs());
                pointData.setDatetime((date));
                pointData.setId(pointList.get(i).getId());
                pointData.setQuality(Quality.GOOD);
                pointData.setBlob(list.get(i).getTsData().getBlobValue().get().getBytes());
                blobList.add(pointData);
            }
            int count = snap.putBlobSnapshots(blobList);
            return count;
        } finally {
            if (connection != null)
                goldenConfig.getGoldenConnectionPool().returnConnection(connection);
        }

    }

    @Override
    public int writeBooleanLatest(List<TsPointData> list) throws Exception {
        ServerImpl connection = null;
        try {
            connection = goldenConfig.getGoldenConnectionPool().getConnection();
            SnapshotImpl snap = new SnapshotImpl(connection);
            BaseImpl base = new BaseImpl(connection);
            String[] tagNames = list.stream().map(TsPointData::getTagName).toArray(String[]::new);
            List<MinPoint> pointList = base.findPoints(tagNames);
            List<IntData> intList = new ArrayList<>();
            for (int i = 0; i < list.size(); i++) {
                IntData pointData = new IntData();
                Date date = new Date();
                date.setTime(list.get(i).getTsData().getTs());
                pointData.setDateTime(date);
                pointData.setId(pointList.get(i).getId());
                pointData.setQuality((short) 0);
                pointData.setValue(list.get(i).getTsData().getBooleanValue().get() ? 1 : 0);
                intList.add(pointData);
            }
            int count = snap.putIntSnapshots(intList);
            return count;
        } finally {
            if (connection != null)
                goldenConfig.getGoldenConnectionPool().returnConnection(connection);
        }
    }

    @Override
    public int writeLongLatest(List<TsPointData> list) throws Exception {
      
        ServerImpl connection = null;
        try {
            connection = goldenConfig.getGoldenConnectionPool().getConnection();
            SnapshotImpl snap = new SnapshotImpl(connection);
            BaseImpl base = new BaseImpl(connection);
            String[] tagNames = list.stream().map(TsPointData::getTagName).toArray(String[]::new);
            List<MinPoint> pointList = base.findPoints(tagNames);
            List<DatetimeData> datetimeList = new ArrayList<>();
            for (int i = 0; i < list.size(); i++) {

                DatetimeData pointData = new DatetimeData();
                Date date = new Date();
                date.setTime(list.get(i).getTsData().getTs());
                pointData.setDateTime(date);
                pointData.setId(pointList.get(i).getId());
                pointData.setQuality((short) 0);
                date.setTime(list.get(i).getTsData().getLongValue().get());
                pointData.setValue(date);
                datetimeList.add(pointData);
            }
            int count = snap.putDatetimeSnapshots(datetimeList).getSucCount();
            return count;
        } finally {
            if (connection != null)
                goldenConfig.getGoldenConnectionPool().returnConnection(connection);
        }
    }

    @Override
    public int writeFloatLatest(List<TsPointData> list) throws Exception {
        ServerImpl connection = null;
        try {
            connection = goldenConfig.getGoldenConnectionPool().getConnection();
            SnapshotImpl snap = new SnapshotImpl(connection);
            BaseImpl base = new BaseImpl(connection);
            String[] tagNames = list.stream().map(TsPointData::getTagName).toArray(String[]::new);
            List<MinPoint> pointList = base.findPoints(tagNames);
            List<DoubleData> doubleList = new ArrayList<>();
            for (int i = 0; i < list.size(); i++) {
                Date time = new Date();
                time.setTime(list.get(0).getTsData().getTs());
                DoubleData data = new DoubleData(pointList.get(i).getId(), time, list.get(i).getTsData().getFloatValue().get()
                        , (short) 0, 0);
                doubleList.add(data);
            }
            int count = snap.putDoubleSnapshots(doubleList);
            return count;
        } finally {
            if (connection != null)
                goldenConfig.getGoldenConnectionPool().returnConnection(connection);
        }
    }

    @Override
    public int writeBlobLatest(List<TsPointData> list) throws Exception {
        ServerImpl connection = null;
        try {
            connection = goldenConfig.getGoldenConnectionPool().getConnection();
            SnapshotImpl snap = new SnapshotImpl(connection);
            BaseImpl base = new BaseImpl(connection);
            String[] tagNames = list.stream().map(TsPointData::getTagName).toArray(String[]::new);
            List<MinPoint> pointList = base.findPoints(tagNames);
            List<BlobData> dataList = new ArrayList<>();
            for (int i = 0; i < list.size(); i++) {

                BlobData pointData = new BlobData();
                Date date = new Date();
                date.setTime(list.get(i).getTsData().getTs());
                pointData.setDatetime((date));
                pointData.setId(pointList.get(i).getId());
                pointData.setQuality(Quality.GOOD);
                pointData.setBlob(list.get(i).getTsData().getBlobValue().get().getBytes());
                pointData.setLen(list.get(i).getTsData().getBlobValue().get().getBytes().length);
                dataList.add(pointData);
            }
            int count = snap.putBlobSnapshots(dataList);
            return count;

        } finally {
            if (connection != null)
                goldenConfig.getGoldenConnectionPool().returnConnection(connection);
        }
    }

    @Override
    public int writeCoordinateLatest(List<TsPointData> list) throws Exception {
        ServerImpl connection = null;
        try {
            connection = goldenConfig.getGoldenConnectionPool().getConnection();
            SnapshotImpl snap = new SnapshotImpl(connection);
            BaseImpl base = new BaseImpl(connection);
            String[] tagNames = list.stream().map(TsPointData::getTagName).toArray(String[]::new);
            List<MinPoint> pointList = base.findPoints(tagNames);
            List<CoorData> dataList = new ArrayList<>();
            for (int i = 0; i < list.size(); i++) {

                CoorData pointData = new CoorData();
                Date date = new Date();
                date.setTime(list.get(i).getTsData().getTs());
                pointData.setDateTime((date));
                pointData.setId(pointList.get(i).getId());
                pointData.setQuality((short) 0);
                pointData.setX((float) list.get(i).getTsData().getCoordinateValue().get().getLongitude());
                pointData.setY((float) list.get(i).getTsData().getCoordinateValue().get().getLatitude());
                dataList.add(pointData);
            }
            int count = snap.putCoorSnapshots(dataList);
            return count;

        } finally {
            if (connection != null)
                goldenConfig.getGoldenConnectionPool().returnConnection(connection);
        }
    }

    @Override
    public boolean writeLatest(List<TsPointData> dataList) throws Exception {
        int writeCount = 0;
        Map<TsDataType, List<TsPointData>> pointGroup = dataList.stream().collect(Collectors.groupingBy(TsPointData::findDataType));
        for (Map.Entry<TsDataType, List<TsPointData>> entry : pointGroup.entrySet()) {
            List<TsPointData> pointDataList = entry.getValue();
            if (entry.getKey() == TsDataType.DOUBLE) {
                int count = writeDoubleLatest(pointDataList);
                writeCount = writeCount + count;
            } else if (entry.getKey() == TsDataType.BOOLEAN) {
                int count = writeBooleanLatest(pointDataList);
                writeCount = writeCount + count;
            } else if (entry.getKey() == TsDataType.STRING) {
                int count = writeStringLatest(pointDataList);
                writeCount = writeCount + count;
            } else if (entry.getKey() == TsDataType.BLOB) {
                int count = writeBlobLatest(pointDataList);
                writeCount = writeCount + count;
            } else if (entry.getKey() == TsDataType.COORDINATE) {
                int count = writeCoordinateLatest(pointDataList);
                writeCount = writeCount + count;
            } else if (entry.getKey() == TsDataType.LONG) {
                int count = writeLongLatest(pointDataList);
                writeCount = writeCount + count;
            } else if (entry.getKey() == TsDataType.FLOAT) {
                int count = writeFloatLatest(pointDataList);
                writeCount = writeCount + count;
            }
        }
        return writeCount > 0 ? true : false;

    }



}
