/*
 * 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 COMMON_DB_COMMON_H
#define COMMON_DB_COMMON_H

#include <iostream>
#include <unordered_set>

#include "common/allocator/my_string.h"
#include "utils/util_define.h"

namespace common {

/**
 * @brief Represents the data type of a measurement.
 *
 * This enumeration defines the supported data types for measurements in the
 * system.
 */
enum TSDataType : uint8_t {
    BOOLEAN = 0,
    INT32 = 1,
    INT64 = 2,
    FLOAT = 3,
    DOUBLE = 4,
    TEXT = 5,
    VECTOR = 6,
    UNKNOWN = 7,
    TIMESTAMP = 8,
    DATE = 9,
    BLOB = 10,
    STRING = 11,
    NULL_TYPE = 254,
    INVALID_DATATYPE = 255
};

/**
 * @brief Represents the encoding method for a measurement.
 *
 * This enumeration defines the supported encoding methods that can be applied
 * to measurements.
 */
enum TSEncoding : uint8_t {
    PLAIN = 0,
    DICTIONARY = 1,
    RLE = 2,
    DIFF = 3,
    TS_2DIFF = 4,
    BITMAP = 5,
    GORILLA_V1 = 6,
    REGULAR = 7,
    GORILLA = 8,
    ZIGZAG = 9,
    FREQ = 10,
    SPRINTZ = 12,
    INVALID_ENCODING = 255
};

/**
 * @brief Represents the compression type for a measurement.
 *
 * This enumeration defines the supported compression methods that can be
 * applied to measurements.
 */
enum CompressionType : uint8_t {
    UNCOMPRESSED = 0,
    SNAPPY = 1,
    GZIP = 2,
    LZO = 3,
    SDT = 4,
    PAA = 5,
    PLA = 6,
    LZ4 = 7,
    INVALID_COMPRESSION = 255
};

extern const char* s_data_type_names[8];
extern const char* s_encoding_names[12];
extern const char* s_compression_names[8];

FORCE_INLINE const char* get_data_type_name(TSDataType type) {
    ASSERT(type >= BOOLEAN && type <= STRING);
    return s_data_type_names[type];
}

FORCE_INLINE const char* get_encoding_name(TSEncoding encoding) {
    ASSERT(encoding >= PLAIN && encoding <= FREQ);
    return s_encoding_names[encoding];
}

FORCE_INLINE const char* get_compression_name(CompressionType type) {
    return s_compression_names[type];
}

enum Ordering { DESC, ASC };

template <typename T>
FORCE_INLINE common::TSDataType GetDataTypeFromTemplateType() {
    return common::INVALID_DATATYPE;
}

template <>
FORCE_INLINE common::TSDataType GetDataTypeFromTemplateType<bool>() {
    return common::BOOLEAN;
}
template <>
FORCE_INLINE common::TSDataType GetDataTypeFromTemplateType<int32_t>() {
    return common::INT32;
}
template <>
FORCE_INLINE common::TSDataType GetDataTypeFromTemplateType<int64_t>() {
    return common::INT64;
}
template <>
FORCE_INLINE common::TSDataType GetDataTypeFromTemplateType<float>() {
    return common::FLOAT;
}
template <>
FORCE_INLINE common::TSDataType GetDataTypeFromTemplateType<double>() {
    return common::DOUBLE;
}
template <>
FORCE_INLINE common::TSDataType GetDataTypeFromTemplateType<common::String>() {
    return common::STRING;
}

template <typename T>
FORCE_INLINE std::unordered_set<common::TSDataType>
GetDataTypesFromTemplateType() {
    return {common::INVALID_DATATYPE};
}

template <>
FORCE_INLINE std::unordered_set<common::TSDataType>
GetDataTypesFromTemplateType<bool>() {
    return {common::BOOLEAN};
}
template <>
FORCE_INLINE std::unordered_set<common::TSDataType>
GetDataTypesFromTemplateType<int32_t>() {
    return {common::INT32, common::DATE, common::INT64};
}
template <>
FORCE_INLINE std::unordered_set<common::TSDataType>
GetDataTypesFromTemplateType<int64_t>() {
    return {common::INT64, TIMESTAMP};
}
template <>
FORCE_INLINE std::unordered_set<common::TSDataType>
GetDataTypesFromTemplateType<float>() {
    return {common::FLOAT, common::DOUBLE};
}
template <>
FORCE_INLINE std::unordered_set<common::TSDataType>
GetDataTypesFromTemplateType<double>() {
    return {common::DOUBLE};
}
template <>
FORCE_INLINE std::unordered_set<common::TSDataType>
GetDataTypesFromTemplateType<common::String>() {
    return {common::STRING, common::TEXT, common::BLOB};
}

FORCE_INLINE size_t get_data_type_size(TSDataType data_type) {
    switch (data_type) {
        case common::BOOLEAN:
            return 1;
        case common::DATE:
        case common::INT32:
        case common::FLOAT:
            return 4;
        case common::INT64:
        case common::TIMESTAMP:
        case common::DOUBLE:
            return 8;
        default:
            ASSERT(false);
            return 8;
    }
}

}  // end namespace common

namespace storage {

struct TimeRange {
    TimeRange() : start_time_(INT64_MAX), end_time_(INT64_MIN) {}
    TimeRange(int64_t start_time, int64_t end_time)
        : start_time_(start_time), end_time_(end_time) {}

    int64_t start_time_;
    int64_t end_time_;
};

}  // namespace storage

#endif
