package cn.gintone.iotdbUtils;

import org.apache.iotdb.isession.pool.SessionDataSetWrapper;
import org.apache.iotdb.rpc.IoTDBConnectionException;
import org.apache.iotdb.rpc.StatementExecutionException;
import org.apache.iotdb.session.pool.SessionPool;
import org.apache.tsfile.enums.TSDataType;
import org.apache.tsfile.file.metadata.enums.CompressionType;
import org.apache.tsfile.file.metadata.enums.TSEncoding;
import org.apache.tsfile.read.common.Field;
import org.apache.tsfile.read.common.RowRecord;
import org.apache.tsfile.write.record.Tablet;
import org.apache.tsfile.write.schema.MeasurementSchema;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class IotDBUtil {


    public static void main(String[] args) {
        select();
    }

    // 创建数据库
    public static void createDatabase() {
        // Using nodeUrls ensures that when one node goes down, other nodes are automatically connected to retry
        try {
            List<String> nodeUrls = new ArrayList<>();
            nodeUrls.add("192.168.19.128:6667");
            SessionPool sessionPool =
                    new SessionPool.Builder()
                            .nodeUrls(nodeUrls)
                            .user("root")
                            .password("root")
                            .maxSize(3)
                            .build();

            sessionPool.createDatabase("root.myDateTestTwo"); // 创建数据库

            sessionPool.close();
        } catch (IoTDBConnectionException e) {
            throw new RuntimeException(e);
        } catch (StatementExecutionException e) {
            throw new RuntimeException(e);
        }
    }

    // 创建对齐时间序列
    public static void createAlignedTimeseries() {
        try {
            List<String> nodeUrls = new ArrayList<>();
            nodeUrls.add("192.168.19.128:6667");
            SessionPool sessionPool =
                    new SessionPool.Builder()
                            .nodeUrls(nodeUrls)
                            .user("root")
                            .password("root")
                            .maxSize(3)
                            .build();


            // 创建对齐时间序列
            List<String> list = new ArrayList<>();
            list.add("userId");
            list.add("userName");
            list.add("url");

            List<TSDataType> list2 = new ArrayList<>();
            list2.add(TSDataType.TEXT);
            list2.add(TSDataType.TEXT);
            list2.add(TSDataType.TEXT);

            List<TSEncoding> list3 = new ArrayList<>();
            list3.add(TSEncoding.PLAIN);
            list3.add(TSEncoding.PLAIN);
            list3.add(TSEncoding.PLAIN);

            List<CompressionType> list4 = new ArrayList<>();
            list4.add(CompressionType.UNCOMPRESSED);
            list4.add(CompressionType.UNCOMPRESSED);
            list4.add(CompressionType.UNCOMPRESSED);

            sessionPool.createAlignedTimeseries("root.myDateTestTwo.tableTwo", list, list2, list3, list4, null);

            sessionPool.close();
        } catch (IoTDBConnectionException e) {
            throw new RuntimeException(e);
        } catch (StatementExecutionException e) {
            throw new RuntimeException(e);
        }

    }

    // 创建时间序列
    public static void createTimeseries() {
        try {
            List<String> nodeUrls = new ArrayList<>();
            nodeUrls.add("192.168.19.128:6667");
            SessionPool sessionPool =
                    new SessionPool.Builder()
                            .nodeUrls(nodeUrls)
                            .user("root")
                            .password("root")
                            .maxSize(3)
                            .build();

            // 设置数据类型，设置默认编码模式，设置默认压缩模式
            sessionPool.createTimeseries("root.myDateTestTwo.tableOne.name", TSDataType.TEXT, TSEncoding.PLAIN, CompressionType.UNCOMPRESSED);
            sessionPool.close();
        } catch (IoTDBConnectionException e) {
            throw new RuntimeException(e);
        } catch (StatementExecutionException e) {
            throw new RuntimeException(e);
        }

    }

    // 单行插入
    public static void inserOne() {
        // Using nodeUrls ensures that when one node goes down, other nodes are automatically connected to retry
        try {
            List<String> nodeUrls = new ArrayList<>();
            nodeUrls.add("192.168.19.128:6667");
            SessionPool sessionPool =
                    new SessionPool.Builder()
                            .nodeUrls(nodeUrls)
                            .user("root")
                            .password("root")
                            .maxSize(3)
                            .build();


            List<String> list5 = new ArrayList<>();
            list5.add("name");
            list5.add("age");

            List<TSDataType> list6 = new ArrayList<>();
            list6.add(TSDataType.TEXT);
            list6.add(TSDataType.INT32);

            List<Object> values = new ArrayList<>();
            values.add("胡懿");
            values.add(31);
            sessionPool.insertRecord("root.myDateTestTwo.tableOne", System.currentTimeMillis(), list5, list6, values);
            sessionPool.close();
        } catch (IoTDBConnectionException e) {
            throw new RuntimeException(e);
        } catch (StatementExecutionException e) {
            throw new RuntimeException(e);
        }
    }

    // 批量插入
    public static void insetAll() {
        try {
            List<String> nodeUrls = new ArrayList<>();
            nodeUrls.add("192.168.19.128:6667");
            SessionPool sessionPool =
                    new SessionPool.Builder()
                            .nodeUrls(nodeUrls)
                            .user("root")
                            .password("root")
                            .maxSize(3)
                            .build();

            List<String> deviceIds = new ArrayList<>();
            List<Long> times = new ArrayList<>();
            List<List<String>> measurementList = new ArrayList<>();
            List<List<TSDataType>> typeList = new ArrayList<>();
            List<List<Object>> valueList = new ArrayList<>();

            for (int i = 0; i < 50; i ++) {
                deviceIds.add("root.myDateTestTwo.tableThree");
                Thread.sleep(30);
                times.add(System.currentTimeMillis());
                List<String> measurements = new ArrayList<>();
                measurements.add("userId");
                measurements.add("userName");
                measurements.add("url");
                measurementList.add(measurements);
                List<TSDataType> types = new ArrayList<>();
                types.add(TSDataType.TEXT);
                types.add(TSDataType.TEXT);
                types.add(TSDataType.TEXT);
                typeList.add(types);

                List<Object> valuexxs = new ArrayList<>();
                valuexxs.add("" + i);
                valuexxs.add("胡懿" + i);
                valuexxs.add("https_" + i);
                valueList.add(valuexxs);
            }

            sessionPool.insertRecords(deviceIds, times, measurementList, typeList, valueList);
            sessionPool.close();
        } catch (IoTDBConnectionException e) {
            throw new RuntimeException(e);
        } catch (StatementExecutionException e) {
            throw new RuntimeException(e);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

    }

    // 向单个表中批量写入数据
    public static void insertTablet() {
        try {
            List<String> nodeUrls = new ArrayList<>();
            nodeUrls.add("192.168.19.128:6667");
            SessionPool sessionPool =
                    new SessionPool.Builder()
                            .nodeUrls(nodeUrls)
                            .user("root")
                            .password("root")
                            .maxSize(3)
                            .build();


            // 设置表属性
            List<MeasurementSchema> schemas = new ArrayList<>();
            schemas.add(new MeasurementSchema("s1",  TSDataType.DOUBLE));
            schemas.add(new MeasurementSchema("s2",  TSDataType.DOUBLE));
            schemas.add(new MeasurementSchema("s3",  TSDataType.DOUBLE));

            Tablet tablet = new Tablet("root.myDateTestTwo.tableFour", schemas, 101); // 最后的100代表设置每次最多添加100条数据


            // 添加数据
            long timeMillis = System.currentTimeMillis();
            Random random = new Random();
            for (int i = 1; i <= 100; i ++) {

                tablet.addTimestamp(i, timeMillis);
                timeMillis += 100;

                for (int s = 0; s < 3; s ++) {
                    int value = random.nextInt(50);
                    tablet.addValue(schemas.get(s).getMeasurementId(), i, value + 0.0);
                }
                tablet.rowSize ++;
            }

            if (tablet.rowSize != 0) {
                sessionPool.insertTablet(tablet);
                tablet.reset();// 清空tablet
            }


            sessionPool.close();
        } catch (IoTDBConnectionException e) {
            throw new RuntimeException(e);
        } catch (StatementExecutionException e) {
            throw new RuntimeException(e);
        }
    }

    // 查询
    public static void select() {
        try {
            List<String> nodeUrls = new ArrayList<>();
            nodeUrls.add("192.168.19.128:6667");
            SessionPool sessionPool =
                    new SessionPool.Builder()
                            .nodeUrls(nodeUrls)
                            .user("root")
                            .password("root")
                            .maxSize(3)
                            .build();

            SessionDataSetWrapper sessionDataSetWrapper = sessionPool.executeQueryStatement("select s1,s2,s3 from root.myDateTestTwo.tableFour");
            List<String> columnNames = sessionDataSetWrapper.getColumnNames();
            System.out.println(columnNames);
            while (sessionDataSetWrapper.hasNext()) {
                RowRecord next = sessionDataSetWrapper.next(); // 取出一行数据
                long timestamp = next.getTimestamp(); // 获取这行的时间戳
                List<Field> fields = next.getFields();
                Field field1 = fields.get(0);
                double s1 = field1.getDoubleV();
                Field field2 = fields.get(1);
                double s2 = field2.getDoubleV();
                Field field3 = fields.get(2);
                double s3 = field3.getDoubleV();
                System.out.println(timestamp + "----" + s1 + "----" + s2 + "-----" + s3);
            }

            sessionPool.close();
        } catch (IoTDBConnectionException e) {
            throw new RuntimeException(e);
        } catch (StatementExecutionException e) {
            throw new RuntimeException(e);
        }

    }

}
