/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
#ifndef IOTDB_SESSION_H
#define IOTDB_SESSION_H

#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <exception>
#include <iostream>
#include <algorithm>
#include <map>
#include <unordered_map>
#include <thread>
#include <stdexcept>
#include <cstdlib>
#include <future>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/protocol/TCompactProtocol.h>
#include <thrift/transport/TSocket.h>
#include <thrift/transport/TTransportException.h>
#include <thrift/transport/TBufferTransports.h>
#include "IClientRPCService.h"
#include "NodesSupplier.h"
#include "AbstractSessionBuilder.h"
#include "SessionConnection.h"
#include "SessionDataSet.h"
#include "DeviceID.h"
#include "Common.h"

//== For compatible with Windows OS ==
#ifndef LONG_LONG_MIN
#define LONG_LONG_MIN 0x8000000000000000
#endif

using namespace std;

using ::apache::thrift::protocol::TBinaryProtocol;
using ::apache::thrift::protocol::TCompactProtocol;
using ::apache::thrift::transport::TSocket;
using ::apache::thrift::transport::TTransport;
using ::apache::thrift::transport::TTransportException;
using ::apache::thrift::transport::TBufferedTransport;
using ::apache::thrift::transport::TFramedTransport;
using ::apache::thrift::TException;


template <typename T, typename Target>
void safe_cast(const T& value, Target& target) {
    /*
        Target	Allowed Source Types
        BOOLEAN	BOOLEAN
        INT32	INT32
        INT64	INT32 INT64
        FLOAT	INT32 FLOAT
        DOUBLE	INT32 INT64 FLOAT DOUBLE
        TEXT	TEXT
    */
    if (std::is_same<Target, T>::value) {
        target = *(Target*)&value;
    }
    else if (std::is_same<Target, string>::value && std::is_array<T>::value && std::is_same<
        char, typename std::remove_extent<T>::type>::value) {
        string tmp((const char*)&value);
        target = *(Target*)&tmp;
    }
    else if (std::is_same<Target, int64_t>::value && std::is_same<T, int32_t>::value) {
        int64_t tmp = *(int32_t*)&value;
        target = *(Target*)&tmp;
    }
    else if (std::is_same<Target, float>::value && std::is_same<T, int32_t>::value) {
        float tmp = *(int32_t*)&value;
        target = *(Target*)&tmp;
    }
    else if (std::is_same<Target, double>::value && std::is_same<T, int32_t>::value) {
        double tmp = *(int32_t*)&value;
        target = *(Target*)&tmp;
    }
    else if (std::is_same<Target, double>::value && std::is_same<T, int64_t>::value) {
        double tmp = *(int64_t*)&value;
        target = *(Target*)&tmp;
    }
    else if (std::is_same<Target, double>::value && std::is_same<T, float>::value) {
        double tmp = *(float*)&value;
        target = *(Target*)&tmp;
    }
    else {
        throw UnSupportedDataTypeException("Error: Parameter type " +
            std::string(typeid(T).name()) + " cannot be converted to DataType" +
            std::string(typeid(Target).name()));
    }
}

/*
 * A tablet data of one device, the tablet contains multiple measurements of this device that share
 * the same time column.
 *
 * for example:  device root.sg1.d1
 *
 * time, m1, m2, m3
 *    1,  1,  2,  3
 *    2,  1,  2,  3
 *    3,  1,  2,  3
 *
 * Notice: The tablet should not have empty cell
 *
 */
class Tablet {
private:
    static const int DEFAULT_ROW_SIZE = 1024;

    void createColumns();
    void deleteColumns();

public:
    std::string deviceId; // deviceId of this tablet
    std::vector<std::pair<std::string, TSDataType::TSDataType>> schemas;
    // the list of measurement schemas for creating the tablet
    std::map<std::string, size_t> schemaNameIndex; // the map of schema name to index
    std::vector<ColumnCategory> columnTypes; // the list of column types (used in table model)
    std::vector<int64_t> timestamps; // timestamps in this tablet
    std::vector<void*> values; // each object is a primitive type array, which represents values of one measurement
    std::vector<BitMap> bitMaps; // each bitmap represents the existence of each value in the current column
    size_t rowSize; //the number of rows to include in this tablet
    size_t maxRowNumber; // the maximum number of rows for this tablet
    bool isAligned; // whether this tablet store data of aligned timeseries or not
    std::vector<int> idColumnIndexes;

    Tablet() = default;

    /**
    * Return a tablet with default specified row number. This is the standard
    * constructor (all Tablet should be the same size).
    *
    * @param deviceId   the name of the device specified to be written in
    * @param timeseries the list of measurement schemas for creating the tablet
    */
    Tablet(const std::string& deviceId,
           const std::vector<std::pair<std::string, TSDataType::TSDataType>>& timeseries)
        : Tablet(deviceId, timeseries, DEFAULT_ROW_SIZE) {
    }

    Tablet(const std::string& deviceId,
           const std::vector<std::pair<std::string, TSDataType::TSDataType>>& timeseries,
           const std::vector<ColumnCategory>& columnTypes)
        : Tablet(deviceId, timeseries, columnTypes, DEFAULT_ROW_SIZE) {
    }

    /**
     * Return a tablet with the specified number of rows (maxBatchSize). Only
     * call this constructor directly for testing purposes. Tablet should normally
     * always be default size.
     *
     * @param deviceId     the name of the device specified to be written in
     * @param schemas   the list of measurement schemas for creating the row
     *                     batch
     * @param columnTypes the list of column types (used in table model)
     * @param maxRowNumber the maximum number of rows for this tablet
     */
    Tablet(const std::string& deviceId,
           const std::vector<std::pair<std::string, TSDataType::TSDataType>>& schemas,
           int maxRowNumber)
        : Tablet(deviceId, schemas, std::vector<ColumnCategory>(schemas.size(), ColumnCategory::FIELD), maxRowNumber) {
    }

    Tablet(const std::string& deviceId, const std::vector<std::pair<std::string, TSDataType::TSDataType>>& schemas,
           const std::vector<ColumnCategory> columnTypes,
           size_t maxRowNumber, bool _isAligned = false) : deviceId(deviceId), schemas(schemas),
                                                           columnTypes(columnTypes),
                                                           maxRowNumber(maxRowNumber), isAligned(_isAligned) {
        // create timestamp column
        timestamps.resize(maxRowNumber);
        // create value columns
        values.resize(schemas.size());
        createColumns();
        // init idColumnIndexs
        for (size_t i = 0; i < this->columnTypes.size(); i++) {
            if (this->columnTypes[i] == ColumnCategory::TAG) {
                idColumnIndexes.push_back(i);
            }
        }
        // create bitMaps
        bitMaps.resize(schemas.size());
        for (size_t i = 0; i < schemas.size(); i++) {
            bitMaps[i].resize(maxRowNumber);
        }
        // create schemaNameIndex
        for (size_t i = 0; i < schemas.size(); i++) {
            schemaNameIndex[schemas[i].first] = i;
        }
        this->rowSize = 0;
    }

    Tablet(const Tablet& other)
        : deviceId(other.deviceId),
          schemas(other.schemas),
          schemaNameIndex(other.schemaNameIndex),
          columnTypes(other.columnTypes),
          timestamps(other.timestamps),
          maxRowNumber(other.maxRowNumber),
          bitMaps(other.bitMaps),
          rowSize(other.rowSize),
          isAligned(other.isAligned),
          idColumnIndexes(other.idColumnIndexes) {
        values.resize(other.values.size());
        for (size_t i = 0; i < other.values.size(); ++i) {
            if (!other.values[i]) continue;
            TSDataType::TSDataType type = schemas[i].second;
            deepCopyTabletColValue(&(other.values[i]), &values[i], type, maxRowNumber);
        }
    }

    Tablet& operator=(const Tablet& other) {
        if (this != &other) {
            deleteColumns();
            deviceId = other.deviceId;
            schemas = other.schemas;
            schemaNameIndex = other.schemaNameIndex;
            columnTypes = other.columnTypes;
            timestamps = other.timestamps;
            maxRowNumber = other.maxRowNumber;
            rowSize = other.rowSize;
            isAligned = other.isAligned;
            idColumnIndexes = other.idColumnIndexes;
            bitMaps = other.bitMaps;
            values.resize(other.values.size());
            for (size_t i = 0; i < other.values.size(); ++i) {
                if (!other.values[i]) continue;
                TSDataType::TSDataType type = schemas[i].second;
                deepCopyTabletColValue(&(other.values[i]), &values[i], type, maxRowNumber);
            }
        }
        return *this;
    }

    ~Tablet() {
        try {
            deleteColumns();
        }
        catch (exception& e) {
            log_debug(string("Tablet::~Tablet(), ") + e.what());
        }
    }

    void addTimestamp(size_t rowIndex, int64_t timestamp) {
        timestamps[rowIndex] = timestamp;
        rowSize = max(rowSize, rowIndex + 1);
    }

    static void deepCopyTabletColValue(void* const* srcPtr, void** destPtr,
        TSDataType::TSDataType type, int maxRowNumber);

    template <typename T>
    void addValue(size_t schemaId, size_t rowIndex, const T& value) {
        if (schemaId >= schemas.size()) {
            char tmpStr[100];
            sprintf(tmpStr, "Tablet::addValue(), schemaId >= schemas.size(). schemaId=%ld, schemas.size()=%ld.",
                    schemaId, schemas.size());
            throw std::out_of_range(tmpStr);
        }

        if (rowIndex >= rowSize) {
            char tmpStr[100];
            sprintf(tmpStr, "Tablet::addValue(), rowIndex >= rowSize. rowIndex=%ld, rowSize.size()=%ld.", rowIndex,
                    rowSize);
            throw std::out_of_range(tmpStr);
        }

        TSDataType::TSDataType dataType = schemas[schemaId].second;
        switch (dataType) {
        case TSDataType::BOOLEAN: {
            safe_cast<T, bool>(value, ((bool*)values[schemaId])[rowIndex]);
            break;
        }
        case TSDataType::INT32: {
            safe_cast<T, int32_t>(value, ((int*)values[schemaId])[rowIndex]);
            break;
        }
        case TSDataType::DATE: {
            safe_cast<T, boost::gregorian::date>(value, ((boost::gregorian::date*)values[schemaId])[rowIndex]);
            break;
        }
        case TSDataType::TIMESTAMP:
        case TSDataType::INT64: {
            safe_cast<T, int64_t>(value, ((int64_t*)values[schemaId])[rowIndex]);
            break;
        }
        case TSDataType::FLOAT: {
            safe_cast<T, float>(value, ((float*)values[schemaId])[rowIndex]);
            break;
        }
        case TSDataType::DOUBLE: {
            safe_cast<T, double>(value, ((double*)values[schemaId])[rowIndex]);
            break;
        }
        case TSDataType::BLOB:
        case TSDataType::STRING:
        case TSDataType::TEXT: {
            safe_cast<T, string>(value, ((string*)values[schemaId])[rowIndex]);
            break;
        }
        default:
            throw UnSupportedDataTypeException(string("Data type ") + to_string(dataType) + " is not supported.");
        }
    }

    template <typename T>
    void addValue(const string& schemaName, size_t rowIndex, const T& value) {
        if (schemaNameIndex.find(schemaName) == schemaNameIndex.end()) {
            throw SchemaNotFoundException(string("Schema ") + schemaName + " not found.");
        }
        size_t schemaId = schemaNameIndex[schemaName];
        addValue(schemaId, rowIndex, value);
    }


    void* getValue(size_t schemaId, size_t rowIndex, TSDataType::TSDataType dataType) {
        if (schemaId >= schemas.size()) {
            throw std::out_of_range("Tablet::getValue schemaId out of range: "
                + std::to_string(schemaId));
        }
        if (rowIndex >= rowSize) {
            throw std::out_of_range("Tablet::getValue rowIndex out of range: "
                + std::to_string(rowIndex));
        }

        switch (dataType) {
        case TSDataType::BOOLEAN:
            return &(reinterpret_cast<bool*>(values[schemaId])[rowIndex]);
        case TSDataType::INT32:
            return &(reinterpret_cast<int32_t*>(values[schemaId])[rowIndex]);
        case TSDataType::DATE:
            return &(reinterpret_cast<boost::gregorian::date*>(values[schemaId])[rowIndex]);
        case TSDataType::TIMESTAMP:
        case TSDataType::INT64:
            return &(reinterpret_cast<int64_t*>(values[schemaId])[rowIndex]);
        case TSDataType::FLOAT:
            return &(reinterpret_cast<float*>(values[schemaId])[rowIndex]);
        case TSDataType::DOUBLE:
            return &(reinterpret_cast<double*>(values[schemaId])[rowIndex]);
        case TSDataType::BLOB:
        case TSDataType::STRING:
        case TSDataType::TEXT:
            return &(reinterpret_cast<std::string*>(values[schemaId])[rowIndex]);
        default:
            throw UnSupportedDataTypeException("Unsupported data type: "
                + std::to_string(dataType));
        }
    }

    std::shared_ptr<storage::IDeviceID> getDeviceID(int i);

    std::vector<std::pair<std::string, TSDataType::TSDataType>> getSchemas() const {
        return schemas;
    }

    void reset(); // Reset Tablet to the default state - set the rowSize to 0

    size_t getTimeBytesSize();

    size_t getValueByteSize(); // total byte size that values occupies

    void setAligned(bool isAligned);
};

class SessionUtils {
public:
    static std::string getTime(const Tablet& tablet);

    static std::string getValue(const Tablet& tablet);

    static bool isTabletContainsSingleDevice(Tablet tablet);
};

class TemplateNode {
public:
    explicit TemplateNode(const std::string& name) : name_(name) {
    }

    const std::string& getName() const {
        return name_;
    }

    virtual const std::unordered_map<std::string, std::shared_ptr<TemplateNode>>& getChildren() const {
        throw BatchExecutionException("Should call exact sub class!");
    }

    virtual bool isMeasurement() = 0;

    virtual bool isAligned() {
        throw BatchExecutionException("Should call exact sub class!");
    }

    virtual std::string serialize() const {
        throw BatchExecutionException("Should call exact sub class!");
    }

private:
    std::string name_;
};

class MeasurementNode : public TemplateNode {
public:
    MeasurementNode(const std::string& name_, TSDataType::TSDataType data_type_, TSEncoding::TSEncoding encoding_,
                    CompressionType::CompressionType compression_type_) : TemplateNode(name_) {
        this->data_type_ = data_type_;
        this->encoding_ = encoding_;
        this->compression_type_ = compression_type_;
    }

    TSDataType::TSDataType getDataType() const {
        return data_type_;
    }

    TSEncoding::TSEncoding getEncoding() const {
        return encoding_;
    }

    CompressionType::CompressionType getCompressionType() const {
        return compression_type_;
    }

    bool isMeasurement() override {
        return true;
    }

    std::string serialize() const override;

private:
    TSDataType::TSDataType data_type_;
    TSEncoding::TSEncoding encoding_;
    CompressionType::CompressionType compression_type_;
};

class InternalNode : public TemplateNode {
public:
    InternalNode(const std::string& name, bool is_aligned) : TemplateNode(name), is_aligned_(is_aligned) {
    }

    void addChild(const InternalNode& node) {
        if (this->children_.count(node.getName())) {
            throw BatchExecutionException("Duplicated child of node in template.");
        }
        this->children_[node.getName()] = std::make_shared<InternalNode>(node);
    }

    void addChild(const MeasurementNode& node) {
        if (this->children_.count(node.getName())) {
            throw BatchExecutionException("Duplicated child of node in template.");
        }
        this->children_[node.getName()] = std::make_shared<MeasurementNode>(node);
    }

    void deleteChild(const TemplateNode& node) {
        this->children_.erase(node.getName());
    }

    const std::unordered_map<std::string, std::shared_ptr<TemplateNode>>& getChildren() const override {
        return children_;
    }

    bool isMeasurement() override {
        return false;
    }

    bool isAligned() override {
        return is_aligned_;
    }

private:
    std::unordered_map<std::string, std::shared_ptr<TemplateNode>> children_;
    bool is_aligned_;
};

namespace TemplateQueryType {
enum TemplateQueryType {
    COUNT_MEASUREMENTS, IS_MEASUREMENT, PATH_EXIST, SHOW_MEASUREMENTS
};
}

class Template {
public:
    Template(const std::string& name, bool is_aligned) : name_(name), is_aligned_(is_aligned) {
    }

    const std::string& getName() const {
        return name_;
    }

    bool isAligned() const {
        return is_aligned_;
    }

    void addToTemplate(const InternalNode& child) {
        if (this->children_.count(child.getName())) {
            throw BatchExecutionException("Duplicated child of node in template.");
        }
        this->children_[child.getName()] = std::make_shared<InternalNode>(child);
    }

    void addToTemplate(const MeasurementNode& child) {
        if (this->children_.count(child.getName())) {
            throw BatchExecutionException("Duplicated child of node in template.");
        }
        this->children_[child.getName()] = std::make_shared<MeasurementNode>(child);
    }

    std::string serialize() const;

private:
    std::string name_;
    std::unordered_map<std::string, std::shared_ptr<TemplateNode>> children_;
    bool is_aligned_;
};

class Session {
private:
    std::string host_;
    int rpcPort_;
    std::string username_;
    std::string password_;
    const TSProtocolVersion::type protocolVersion_ = TSProtocolVersion::IOTDB_SERVICE_PROTOCOL_V3;
    bool isClosed_ = true;
    std::string zoneId_;
    int fetchSize_;
    const static int DEFAULT_FETCH_SIZE = 10000;
    const static int DEFAULT_TIMEOUT_MS = 0;
    Version::Version version;
    std::string sqlDialect_ = "tree"; // default sql dialect
    std::string database_;
    bool enableAutoFetch_ = true;
    bool enableRedirection_ = true;
    std::shared_ptr<INodesSupplier> nodesSupplier_;
    friend class SessionConnection;
    friend class TableSession;
    std::shared_ptr<SessionConnection> defaultSessionConnection_;

    TEndPoint defaultEndPoint_;

    struct TEndPointHash {
        size_t operator()(const TEndPoint& endpoint) const {
            return std::hash<std::string>()(endpoint.ip) ^ std::hash<int>()(endpoint.port);
        }
    };

    struct TEndPointEqual {
        bool operator()(const TEndPoint& lhs, const TEndPoint& rhs) const {
            return lhs.ip == rhs.ip && lhs.port == rhs.port;
        }
    };

    using EndPointSessionMap = std::unordered_map<
        TEndPoint, shared_ptr<SessionConnection>, TEndPointHash, TEndPointEqual>;
    EndPointSessionMap endPointToSessionConnection;
    std::unordered_map<std::string, TEndPoint> deviceIdToEndpoint;
    std::unordered_map<std::shared_ptr<storage::IDeviceID>, TEndPoint> tableModelDeviceIdToEndpoint;

private:
    void removeBrokenSessionConnection(shared_ptr<SessionConnection> sessionConnection);

    static bool checkSorted(const Tablet& tablet);

    static bool checkSorted(const std::vector<int64_t>& times);

    static void sortTablet(Tablet& tablet);

    static void sortIndexByTimestamp(int* index, std::vector<int64_t>& timestamps, int length);

    void appendValues(std::string& buffer, const char* value, int size);

    void
    putValuesIntoBuffer(const std::vector<TSDataType::TSDataType>& types, const std::vector<char*>& values,
                        std::string& buf);

    int8_t getDataTypeNumber(TSDataType::TSDataType type);

    struct TsCompare {
        std::vector<int64_t>& timestamps;

        explicit TsCompare(std::vector<int64_t>& inTimestamps) : timestamps(inTimestamps) {
        };

        bool operator()(int i, int j) { return (timestamps[i] < timestamps[j]); };
    };

    std::string getVersionString(Version::Version version);

    void initZoneId();

    void initNodesSupplier();

    void initDefaultSessionConnection();

    template <typename T, typename InsertConsumer>
    void insertByGroup(std::unordered_map<std::shared_ptr<SessionConnection>, T>& insertGroup,
                       InsertConsumer insertConsumer);

    template <typename T, typename InsertConsumer>
    void insertOnce(std::unordered_map<std::shared_ptr<SessionConnection>, T>& insertGroup,
                    InsertConsumer insertConsumer);

    void insertStringRecordsWithLeaderCache(vector<string> deviceIds, vector<int64_t> times,
                                            vector<vector<string>> measurementsList, vector<vector<string>> valuesList,
                                            bool isAligned);

    void insertRecordsWithLeaderCache(vector<string> deviceIds, vector<int64_t> times,
                                      vector<vector<string>> measurementsList,
                                      const vector<vector<TSDataType::TSDataType>>& typesList,
                                      vector<vector<char*>> valuesList, bool isAligned);

    void insertTabletsWithLeaderCache(unordered_map<string, Tablet*> tablets, bool sorted, bool isAligned);

    shared_ptr<SessionConnection> getQuerySessionConnection();

    shared_ptr<SessionConnection> getSessionConnection(std::string deviceId);

    shared_ptr<SessionConnection> getSessionConnection(std::shared_ptr<storage::IDeviceID> deviceId);

    void handleQueryRedirection(TEndPoint endPoint);

    void handleRedirection(const std::string& deviceId, TEndPoint endPoint);

    void handleRedirection(const std::shared_ptr<storage::IDeviceID>& deviceId, TEndPoint endPoint);

    void setSqlDialect(const std::string& dialect) {
        this->sqlDialect_ = dialect;
    }

    void setDatabase(const std::string& database) {
        this->database_ = database;
    }

    string getDatabase() {
        return database_;
    }

    void changeDatabase(string database) {
        this->database_ = database;
    }

public:
    Session(const std::string& host, int rpcPort) : username_("root"), password_("root"), version(Version::V_1_0) {
        this->host_ = host;
        this->rpcPort_ = rpcPort;
        initZoneId();
        initNodesSupplier();
    }

    Session(const std::string& host, int rpcPort, const std::string& username, const std::string& password)
        : fetchSize_(DEFAULT_FETCH_SIZE) {
        this->host_ = host;
        this->rpcPort_ = rpcPort;
        this->username_ = username;
        this->password_ = password;
        this->version = Version::V_1_0;
        initZoneId();
        initNodesSupplier();
    }

    Session(const std::string& host, int rpcPort, const std::string& username, const std::string& password,
            const std::string& zoneId, int fetchSize = DEFAULT_FETCH_SIZE) {
        this->host_ = host;
        this->rpcPort_ = rpcPort;
        this->username_ = username;
        this->password_ = password;
        this->zoneId_ = zoneId;
        this->fetchSize_ = fetchSize;
        this->version = Version::V_1_0;
        initZoneId();
        initNodesSupplier();
    }

    Session(const std::string& host, const std::string& rpcPort, const std::string& username = "user",
            const std::string& password = "password", const std::string& zoneId = "",
            int fetchSize = DEFAULT_FETCH_SIZE) {
        this->host_ = host;
        this->rpcPort_ = stoi(rpcPort);
        this->username_ = username;
        this->password_ = password;
        this->zoneId_ = zoneId;
        this->fetchSize_ = fetchSize;
        this->version = Version::V_1_0;
        initZoneId();
        initNodesSupplier();
    }

    Session(AbstractSessionBuilder* builder) {
        this->host_ = builder->host;
        this->rpcPort_ = builder->rpcPort;
        this->username_ = builder->username;
        this->password_ = builder->password;
        this->zoneId_ = builder->zoneId;
        this->fetchSize_ = builder->fetchSize;
        this->version = Version::V_1_0;
        this->sqlDialect_ = builder->sqlDialect;
        this->database_ = builder->database;
        this->enableAutoFetch_ = builder->enableAutoFetch;
        this->enableRedirection_ = builder->enableRedirections;
        initZoneId();
        initNodesSupplier();
    }

    ~Session();

    void open();

    void open(bool enableRPCCompression);

    void open(bool enableRPCCompression, int connectionTimeoutInMs);

    void close();

    void setTimeZone(const std::string& zoneId);

    std::string getTimeZone();

    void insertRecord(const std::string& deviceId, int64_t time, const std::vector<std::string>& measurements,
                      const std::vector<std::string>& values);

    void insertRecord(const std::string& deviceId, int64_t time, const std::vector<std::string>& measurements,
                      const std::vector<TSDataType::TSDataType>& types, const std::vector<char*>& values);

    void insertAlignedRecord(const std::string& deviceId, int64_t time, const std::vector<std::string>& measurements,
                             const std::vector<std::string>& values);

    void insertAlignedRecord(const std::string& deviceId, int64_t time, const std::vector<std::string>& measurements,
                             const std::vector<TSDataType::TSDataType>& types, const std::vector<char*>& values);

    void insertRecords(const std::vector<std::string>& deviceIds,
                       const std::vector<int64_t>& times,
                       const std::vector<std::vector<std::string>>& measurementsList,
                       const std::vector<std::vector<std::string>>& valuesList);

    void insertRecords(const std::vector<std::string>& deviceIds,
                       const std::vector<int64_t>& times,
                       const std::vector<std::vector<std::string>>& measurementsList,
                       const std::vector<std::vector<TSDataType::TSDataType>>& typesList,
                       const std::vector<std::vector<char*>>& valuesList);

    void insertAlignedRecords(const std::vector<std::string>& deviceIds,
                              const std::vector<int64_t>& times,
                              const std::vector<std::vector<std::string>>& measurementsList,
                              const std::vector<std::vector<std::string>>& valuesList);

    void insertAlignedRecords(const std::vector<std::string>& deviceIds,
                              const std::vector<int64_t>& times,
                              const std::vector<std::vector<std::string>>& measurementsList,
                              const std::vector<std::vector<TSDataType::TSDataType>>& typesList,
                              const std::vector<std::vector<char*>>& valuesList);

    void insertRecordsOfOneDevice(const std::string& deviceId,
                                  std::vector<int64_t>& times,
                                  std::vector<std::vector<std::string>>& measurementsList,
                                  std::vector<std::vector<TSDataType::TSDataType>>& typesList,
                                  std::vector<std::vector<char*>>& valuesList);

    void insertRecordsOfOneDevice(const std::string& deviceId,
                                  std::vector<int64_t>& times,
                                  std::vector<std::vector<std::string>>& measurementsList,
                                  std::vector<std::vector<TSDataType::TSDataType>>& typesList,
                                  std::vector<std::vector<char*>>& valuesList,
                                  bool sorted);

    void insertAlignedRecordsOfOneDevice(const std::string& deviceId,
                                         std::vector<int64_t>& times,
                                         std::vector<std::vector<std::string>>& measurementsList,
                                         std::vector<std::vector<TSDataType::TSDataType>>& typesList,
                                         std::vector<std::vector<char*>>& valuesList);

    void insertAlignedRecordsOfOneDevice(const std::string& deviceId,
                                         std::vector<int64_t>& times,
                                         std::vector<std::vector<std::string>>& measurementsList,
                                         std::vector<std::vector<TSDataType::TSDataType>>& typesList,
                                         std::vector<std::vector<char*>>& valuesList,
                                         bool sorted);

    void insertTablet(Tablet& tablet);

    void insertTablet(Tablet& tablet, bool sorted);

    static void buildInsertTabletReq(TSInsertTabletReq& request, Tablet& tablet, bool sorted);

    void insertTablet(TSInsertTabletReq request);

    void insertAlignedTablet(Tablet& tablet);

    void insertAlignedTablet(Tablet& tablet, bool sorted);

    void insertTablets(std::unordered_map<std::string, Tablet*>& tablets);

    void insertTablets(std::unordered_map<std::string, Tablet*>& tablets, bool sorted);

    void insertAlignedTablets(std::unordered_map<std::string, Tablet*>& tablets, bool sorted = false);

    void testInsertRecord(const std::string& deviceId, int64_t time,
                          const std::vector<std::string>& measurements,
                          const std::vector<std::string>& values);

    void testInsertTablet(const Tablet& tablet);

    void testInsertRecords(const std::vector<std::string>& deviceIds,
                           const std::vector<int64_t>& times,
                           const std::vector<std::vector<std::string>>& measurementsList,
                           const std::vector<std::vector<std::string>>& valuesList);

    void deleteTimeseries(const std::string& path);

    void deleteTimeseries(const std::vector<std::string>& paths);

    void deleteData(const std::string& path, int64_t endTime);

    void deleteData(const std::vector<std::string>& paths, int64_t endTime);

    void deleteData(const std::vector<std::string>& paths, int64_t startTime, int64_t endTime);

    void setStorageGroup(const std::string& storageGroupId);

    void deleteStorageGroup(const std::string& storageGroup);

    void deleteStorageGroups(const std::vector<std::string>& storageGroups);

    void createDatabase(const std::string& database);

    void deleteDatabase(const std::string& database);

    void deleteDatabases(const std::vector<std::string>& databases);

    void createTimeseries(const std::string& path, TSDataType::TSDataType dataType, TSEncoding::TSEncoding encoding,
                          CompressionType::CompressionType compressor);

    void createTimeseries(const std::string& path, TSDataType::TSDataType dataType, TSEncoding::TSEncoding encoding,
                          CompressionType::CompressionType compressor,
                          std::map<std::string, std::string>* props, std::map<std::string, std::string>* tags,
                          std::map<std::string, std::string>* attributes,
                          const std::string& measurementAlias);

    void createMultiTimeseries(const std::vector<std::string>& paths,
                               const std::vector<TSDataType::TSDataType>& dataTypes,
                               const std::vector<TSEncoding::TSEncoding>& encodings,
                               const std::vector<CompressionType::CompressionType>& compressors,
                               std::vector<std::map<std::string, std::string>>* propsList,
                               std::vector<std::map<std::string, std::string>>* tagsList,
                               std::vector<std::map<std::string, std::string>>* attributesList,
                               std::vector<std::string>* measurementAliasList);

    void createAlignedTimeseries(const std::string& deviceId,
                                 const std::vector<std::string>& measurements,
                                 const std::vector<TSDataType::TSDataType>& dataTypes,
                                 const std::vector<TSEncoding::TSEncoding>& encodings,
                                 const std::vector<CompressionType::CompressionType>& compressors);

    bool checkTimeseriesExists(const std::string& path);

    std::unique_ptr<SessionDataSet> executeQueryStatement(const std::string& sql);

    std::unique_ptr<SessionDataSet> executeQueryStatement(const std::string& sql, int64_t timeoutInMs);

    std::unique_ptr<SessionDataSet> executeQueryStatementMayRedirect(const std::string& sql, int64_t timeoutInMs);

    void executeNonQueryStatement(const std::string& sql);

    std::unique_ptr<SessionDataSet> executeRawDataQuery(const std::vector<std::string>& paths, int64_t startTime,
                                                        int64_t endTime);

    std::unique_ptr<SessionDataSet> executeLastDataQuery(const std::vector<std::string>& paths);

    std::unique_ptr<SessionDataSet> executeLastDataQuery(const std::vector<std::string>& paths, int64_t lastTime);

    void createSchemaTemplate(const Template& templ);

    void setSchemaTemplate(const std::string& template_name, const std::string& prefix_path);

    void unsetSchemaTemplate(const std::string& prefix_path, const std::string& template_name);

    void addAlignedMeasurementsInTemplate(const std::string& template_name,
                                          const std::vector<std::string>& measurements,
                                          const std::vector<TSDataType::TSDataType>& dataTypes,
                                          const std::vector<TSEncoding::TSEncoding>& encodings,
                                          const std::vector<CompressionType::CompressionType>& compressors);

    void addAlignedMeasurementsInTemplate(const std::string& template_name,
                                          const std::string& measurement,
                                          TSDataType::TSDataType dataType,
                                          TSEncoding::TSEncoding encoding,
                                          CompressionType::CompressionType compressor);

    void addUnalignedMeasurementsInTemplate(const std::string& template_name,
                                            const std::vector<std::string>& measurements,
                                            const std::vector<TSDataType::TSDataType>& dataTypes,
                                            const std::vector<TSEncoding::TSEncoding>& encodings,
                                            const std::vector<CompressionType::CompressionType>& compressors);

    void addUnalignedMeasurementsInTemplate(const std::string& template_name,
                                            const std::string& measurement,
                                            TSDataType::TSDataType dataType,
                                            TSEncoding::TSEncoding encoding,
                                            CompressionType::CompressionType compressor);

    void deleteNodeInTemplate(const std::string& template_name, const std::string& path);

    int countMeasurementsInTemplate(const std::string& template_name);

    bool isMeasurementInTemplate(const std::string& template_name, const std::string& path);

    bool isPathExistInTemplate(const std::string& template_name, const std::string& path);

    std::vector<std::string> showMeasurementsInTemplate(const std::string& template_name);

    std::vector<std::string> showMeasurementsInTemplate(const std::string& template_name, const std::string& pattern);

    bool checkTemplateExists(const std::string& template_name);
};

template <typename T, typename InsertConsumer>
void Session::insertByGroup(std::unordered_map<std::shared_ptr<SessionConnection>, T>& insertGroup,
                            InsertConsumer insertConsumer) {
    std::vector<std::future<void>> futures;

    for (auto& entry : insertGroup) {
        auto connection = entry.first;
        auto& req = entry.second;
        futures.emplace_back(std::async(std::launch::async, [=, &req]() mutable {
            try {
                insertConsumer(connection, req);
            }
            catch (const RedirectException& e) {
                for (const auto& deviceEndPoint : e.deviceEndPointMap) {
                    handleRedirection(deviceEndPoint.first, deviceEndPoint.second);
                }
            } catch (const IoTDBConnectionException& e) {
                if (endPointToSessionConnection.size() > 1) {
                    removeBrokenSessionConnection(connection);
                    try {
                        insertConsumer(defaultSessionConnection_, req);
                    }
                    catch (const RedirectException&) {
                    }
                }
                else {
                    throw;
                }
            } catch (const std::exception& e) {
                log_debug(e.what());
                throw IoTDBException(e.what());
            }
        }));
    }

    std::string errorMessages;
    for (auto& f : futures) {
        try {
            f.get();
        }
        catch (const IoTDBConnectionException& e) {
            throw;
        } catch (const std::exception& e) {
            if (!errorMessages.empty()) {
                errorMessages += ";";
            }
            errorMessages += e.what();
        }
    }

    if (!errorMessages.empty()) {
        throw StatementExecutionException(errorMessages);
    }
}

template <typename T, typename InsertConsumer>
void Session::insertOnce(std::unordered_map<std::shared_ptr<SessionConnection>, T>& insertGroup,
                         InsertConsumer insertConsumer) {
    auto connection = insertGroup.begin()->first;
    auto req = insertGroup.begin()->second;
    try {
        insertConsumer(connection, req);
    }
    catch (RedirectException e) {
        for (const auto& deviceEndPoint : e.deviceEndPointMap) {
            handleRedirection(deviceEndPoint.first, deviceEndPoint.second);
        }
    } catch (IoTDBConnectionException e) {
        if (endPointToSessionConnection.size() > 1) {
            removeBrokenSessionConnection(connection);
            try {
                insertConsumer(defaultSessionConnection_, req);
            }
            catch (RedirectException e) {
            }
        }
        else {
            throw e;
        }
    }
}

#endif // IOTDB_SESSION_H
