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

#include <stdint.h>
#include <stdio.h>
#include <string.h>  // memcpy

#include <chrono>
#include <iostream>
#include <sstream>
#include <string>

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

namespace common {
extern TSEncoding get_value_encoder(TSDataType data_type);
extern CompressionType get_default_compressor();
/**
 * @brief Represents the schema information for a single measurement.
 * @brief Represents the category of a column in a table schema.
 *
 * This enumeration class defines the supported categories for columns within a
 * table schema, distinguishing between tag and field columns.
 */
enum class ColumnCategory { TAG = 0, FIELD = 1, ATTRIBUTE = 2, TIME = 3 };

/**
 * @brief Represents the schema information for a single column.
 *
 * This structure holds the metadata necessary to describe how a specific column
 * is stored, including its name, data type, category.
 */
struct ColumnSchema {
    std::string column_name_;
    TSDataType data_type_;
    CompressionType compression_;
    TSEncoding encoding_;
    ColumnCategory column_category_;

    ColumnSchema()
        : column_name_(""),
          data_type_(INVALID_DATATYPE),
          compression_(UNCOMPRESSED),
          encoding_(PLAIN),
          column_category_(ColumnCategory::FIELD) {}

    /**
     * @brief Constructs a ColumnSchema object with the given parameters.
     *
     * @param column_name The name of the column. Must be a non-empty string.
     *                    This name is used to identify the column within the
     * table.
     * @param data_type The data type of the measurement, such as INT32, DOUBLE,
     * TEXT, etc. This determines how the data will be stored and interpreted.
     * @param column_category The category of the column indicating its role or
     * type within the schema, e.g., FIELD, TAG. Defaults to
     * ColumnCategory::FIELD if not specified.
     * @note It is the responsibility of the caller to ensure that `column_name`
     * is not empty.
     */
    ColumnSchema(std::string column_name, TSDataType data_type,
                 CompressionType compression, TSEncoding encoding,
                 ColumnCategory column_category = ColumnCategory::FIELD)
        : column_name_(std::move(column_name)),
          data_type_(data_type),
          compression_(compression),
          encoding_(encoding),
          column_category_(column_category) {}

    ColumnSchema(std::string column_name, TSDataType data_type,
                 ColumnCategory column_category = ColumnCategory::FIELD)
        : column_name_(std::move(column_name)),
          data_type_(data_type),
          compression_(get_default_compressor()),
          encoding_(get_value_encoder(data_type)),
          column_category_(column_category) {}

    const std::string& get_column_name() const { return column_name_; }
    const TSDataType& get_data_type() const { return data_type_; }
    const ColumnCategory& get_column_category() const {
        return column_category_;
    }
    const CompressionType& get_compression() const { return compression_; }
    const TSEncoding& get_encoding() const { return encoding_; }
    bool operator==(const ColumnSchema& other) const {
        return (data_type_ == other.data_type_ &&
                encoding_ == other.encoding_ &&
                compression_ == other.compression_ &&
                column_name_ == other.column_name_);
    }

    bool operator!=(const ColumnSchema& other) const {
        return (data_type_ != other.data_type_ ||
                encoding_ != other.encoding_ ||
                compression_ != other.compression_ ||
                column_name_ != other.column_name_);
    }

    bool is_valid() const {
        return data_type_ != INVALID_DATATYPE &&
               encoding_ != INVALID_ENCODING &&
               compression_ != INVALID_COMPRESSION;
    }

    void reset() {
        // TODO
    }

    void get_device_name(char* ret_device_name_buf, const int buf_len,
                         uint32_t& ret_len) const {
        int pos = column_name_.find_last_of('.');
        ASSERT(pos > 0 && pos < buf_len);
        memcpy(ret_device_name_buf, column_name_.c_str(), pos);
        ret_device_name_buf[pos] = '\0';
        ret_len = pos;
    }
    std::string get_device_name_str() const {
        int pos = column_name_.find_last_of('.');
        ASSERT(pos > 0);
        return column_name_.substr(0, pos);
    }
    void get_device_name(String& device_name) const {
        int pos = column_name_.find_last_of('.');
        ASSERT(pos > 0);
        const char* c_string = column_name_.c_str();
        device_name.buf_ = (char*)c_string;
        device_name.len_ = pos;
    }
    void get_measurement_name(char* ret_measurement_name_buf, const int buf_len,
                              uint32_t& ret_len) const {
        int pos = column_name_.find_last_of('.');
        ASSERT(pos > 0 && pos < buf_len);
        ret_len = column_name_.size() - pos - 1;
        memcpy(ret_measurement_name_buf, column_name_.c_str() + pos + 1,
               ret_len);
        ret_measurement_name_buf[ret_len] = '\0';
    }
    std::string get_measurement_name_str() const {
        int pos = column_name_.find_last_of('.');
        ASSERT(pos > 0);
        return column_name_.substr(pos + 1, column_name_.size() - pos);
    }
    // TODO remove
    void get_measurement_name(String& measurement_name) const {
        int pos = column_name_.find_last_of('.');
        ASSERT(pos > 0);
        const char* c_string = column_name_.c_str();
        measurement_name.buf_ = (char*)c_string + pos + 1;
        measurement_name.len_ = column_name_.size() - pos - 1;
    }
    String get_measurement_name() {
        int pos = column_name_.find_last_of('.');
        ASSERT(pos > 0);
        const char* c_string = column_name_.c_str();
        String res;
        res.buf_ = (char*)c_string + pos + 1;
        res.len_ = column_name_.size() - pos - 1;
        return res;
    }

#ifdef DEBUG
    std::string debug_string()  // for debug
    {
        std::stringstream out;
        out << "print ColumnSchema: " << this << std::endl
            << "name: " << column_name_.c_str() << std::endl
            << "datatype: " << get_data_type_name(data_type_) << std::endl
            << "encoding: " << get_encoding_name(encoding_) << std::endl
            << "compression:" << get_compression_name(compression_)
            << std::endl;
        return out.str();
    }
#endif
};

FORCE_INLINE int64_t get_cur_timestamp() {
    return std::chrono::duration_cast<std::chrono::milliseconds>(
               std::chrono::system_clock::now().time_since_epoch())
        .count();
}
}  // end namespace common

#endif  // UTILS_UTILS_H
