/*
 * 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,
    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 TSFILE_API const char* s_data_type_names[8];
extern TSFILE_API const char* s_encoding_names[12];
extern TSFILE_API const char* s_compression_names[8];
}  // 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 <= 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 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
