/*
 * 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 <cctype>
#include <functional>
#include <iostream>
#include <string>
#include <type_traits>
#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,
    CHIMP = 11,
    SPRINTZ = 12,
    RLBE = 13,
    CAMEL = 14,
    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,
    ZSTD = 8,
    LZMA2 = 9,
    INVALID_COMPRESSION = 255
};

extern TSFILE_API const char* s_data_type_names[12];
extern TSFILE_API const char* s_encoding_names[15];
extern TSFILE_API const char* s_compression_names[10];
}  // namespace common

#if defined(__GLIBCXX__) && (__GNUC__ < 7)
namespace std {
template <>
struct hash<common::TSDataType> {
    size_t operator()(common::TSDataType v) const noexcept {
        return static_cast<size_t>(static_cast<uint8_t>(v));
    }
};
}  // namespace std
#endif

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

// Parse a case-insensitive type name (e.g. "int32", "TIMESTAMP") into its
// TSDataType. Covers every named scalar type, not just the subset in
// s_data_type_names, so callers such as the CLI importer can accept the full
// set. Returns false for unrecognized names.
FORCE_INLINE bool parse_data_type_name(const std::string& s, TSDataType& out) {
    std::string u;
    u.reserve(s.size());
    for (char c : s) {
        u += static_cast<char>(std::toupper(static_cast<unsigned char>(c)));
    }
    if (u == "BOOLEAN") {
        out = BOOLEAN;
    } else if (u == "INT32") {
        out = INT32;
    } else if (u == "INT64") {
        out = INT64;
    } else if (u == "FLOAT") {
        out = FLOAT;
    } else if (u == "DOUBLE") {
        out = DOUBLE;
    } else if (u == "TEXT") {
        out = TEXT;
    } else if (u == "STRING") {
        out = STRING;
    } else if (u == "TIMESTAMP") {
        out = TIMESTAMP;
    } else if (u == "DATE") {
        out = DATE;
    } else if (u == "BLOB") {
        out = BLOB;
    } else {
        return false;
    }
    return true;
}

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

FORCE_INLINE const char* get_compression_name(CompressionType type) {
    ASSERT(type >= UNCOMPRESSED && type <= LZMA2);
    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 bool TypeMatch(common::TSDataType dt) {
    return dt == common::INVALID_DATATYPE;
}

template <>
FORCE_INLINE bool TypeMatch<bool>(common::TSDataType dt) {
    return dt == common::BOOLEAN;
}

template <>
FORCE_INLINE bool TypeMatch<int32_t>(common::TSDataType dt) {
    return dt == common::INT32 || dt == common::DATE || dt == common::INT64;
}

template <>
FORCE_INLINE bool TypeMatch<int64_t>(common::TSDataType dt) {
    return dt == common::INT64 || dt == common::TIMESTAMP;
}

template <>
FORCE_INLINE bool TypeMatch<float>(common::TSDataType dt) {
    return dt == common::FLOAT || dt == common::DOUBLE;
}

template <>
FORCE_INLINE bool TypeMatch<double>(common::TSDataType dt) {
    return dt == common::DOUBLE;
}

template <>
FORCE_INLINE bool TypeMatch<common::String>(common::TSDataType dt) {
    return dt == common::STRING || dt == common::TEXT || dt == 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
