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

#include <algorithm>
#include <memory>
#include <vector>

#include "common/config/config.h"
#include "common/container/bit_map.h"
#include "common/db_common.h"
#include "device_id.h"
#include "schema.h"

namespace storage {

template <typename T>

class TabletRowIterator;
class TabletColIterator;

/**
 * @brief Represents a collection of data rows with associated metadata for
 * insertion into a table.
 *
 * This class is used to manage and organize data that will be inserted into a
 * specific target table. It handles the storage of timestamps and values, along
 * with their associated metadata such as column names and types.
 */
class Tablet {
    // Arrow-style string column: offsets + contiguous buffer.
    // string[i] = buffer + offsets[i], len = offsets[i+1] - offsets[i]
    struct StringColumn {
        uint32_t* offsets;      // length: max_rows + 1
        char* buffer;           // contiguous string data
        uint32_t buf_capacity;  // allocated buffer size
        uint32_t buf_used;      // bytes written so far

        StringColumn()
            : offsets(nullptr), buffer(nullptr), buf_capacity(0), buf_used(0) {}

        void init(uint32_t max_rows, uint32_t init_buf_capacity) {
            offsets = (uint32_t*)common::mem_alloc(
                sizeof(uint32_t) * (max_rows + 1), common::MOD_TABLET);
            offsets[0] = 0;
            buf_capacity = init_buf_capacity;
            buffer = (char*)common::mem_alloc(buf_capacity, common::MOD_TABLET);
            buf_used = 0;
        }

        void destroy() {
            if (offsets) common::mem_free(offsets);
            offsets = nullptr;
            if (buffer) common::mem_free(buffer);
            buffer = nullptr;
            buf_capacity = buf_used = 0;
        }

        void reset() {
            buf_used = 0;
            if (offsets) offsets[0] = 0;
        }

        void append(uint32_t row, const char* data, uint32_t len) {
            // Grow buffer if needed
            if (buf_used + len > buf_capacity) {
                buf_capacity = buf_capacity * 2 + len;
                buffer = (char*)common::mem_realloc(buffer, buf_capacity);
            }
            memcpy(buffer + buf_used, data, len);
            offsets[row] = buf_used;
            offsets[row + 1] = buf_used + len;
            buf_used += len;
        }

        const char* get_str(uint32_t row) const {
            return buffer + offsets[row];
        }
        uint32_t get_len(uint32_t row) const {
            return offsets[row + 1] - offsets[row];
        }
        // Return a String view for a given row. The returned reference is
        // valid until the next call to get_string_view on this column.
        common::String& get_string_view(uint32_t row) {
            view_cache_.buf_ = buffer + offsets[row];
            view_cache_.len_ = offsets[row + 1] - offsets[row];
            return view_cache_;
        }

       private:
        common::String view_cache_;
    };

    struct ValueMatrixEntry {
        union {
            int32_t* int32_data;
            int64_t* int64_data;
            float* float_data;
            double* double_data;
            bool* bool_data;
            StringColumn* string_col;
        };
    };

   public:
    static const uint32_t DEFAULT_MAX_ROWS = 1024;
    int err_code_ = common::E_OK;

   public:
    Tablet(const std::string& device_id,
           std::shared_ptr<std::vector<MeasurementSchema>> schema_vec,
           int max_rows = DEFAULT_MAX_ROWS)
        : max_row_num_(max_rows),
          insert_target_name_(device_id),
          schema_vec_(schema_vec),
          timestamps_(nullptr),
          value_matrix_(nullptr),
          bitmaps_(nullptr) {
        ASSERT(device_id.size() >= 1);
        ASSERT(schema_vec != NULL);
        ASSERT(max_rows > 0 && max_rows < (1 << 30));
        if (max_rows < 0) {
            ASSERT(false);
            max_row_num_ = DEFAULT_MAX_ROWS;
        }
        err_code_ = init();
    }

    Tablet(const std::string& device_id,
           const std::vector<std::string>* measurement_list,
           const std::vector<common::TSDataType>* data_type_list,
           int max_row_num = DEFAULT_MAX_ROWS)
        : max_row_num_(max_row_num),
          insert_target_name_(device_id),
          timestamps_(nullptr),
          value_matrix_(nullptr),
          bitmaps_(nullptr) {
        ASSERT(!device_id.empty());
        ASSERT(measurement_list != nullptr);
        ASSERT(data_type_list != nullptr);
        ASSERT(max_row_num > 0 && max_row_num < (1 << 30));
        if (max_row_num < 0) {
            ASSERT(false);
            max_row_num_ = DEFAULT_MAX_ROWS;
        }

        ASSERT(measurement_list->size() == data_type_list->size());
        std::vector<MeasurementSchema> measurement_vec;
        measurement_vec.reserve(measurement_list->size());
        std::transform(measurement_list->begin(), measurement_list->end(),
                       data_type_list->begin(),
                       std::back_inserter(measurement_vec),
                       [](const std::string& name, common::TSDataType type) {
                           return MeasurementSchema(name, type);
                       });
        schema_vec_ =
            std::make_shared<std::vector<MeasurementSchema>>(measurement_vec);
        err_code_ = init();
    }

    Tablet(const std::string& insert_target_name,
           const std::vector<std::string>& column_names,
           const std::vector<common::TSDataType>& data_types,
           const std::vector<common::ColumnCategory>& column_categories,
           int max_rows = DEFAULT_MAX_ROWS)
        : max_row_num_(max_rows),
          cur_row_size_(0),
          insert_target_name_(insert_target_name),
          timestamps_(nullptr),
          value_matrix_(nullptr),
          bitmaps_(nullptr) {
        schema_vec_ = std::make_shared<std::vector<MeasurementSchema>>();
        for (size_t i = 0; i < column_names.size(); i++) {
            schema_vec_->emplace_back(
                MeasurementSchema(column_names[i], data_types[i],
                                  common::get_value_encoder(data_types[i]),
                                  common::get_default_compressor()));
        }
        set_column_categories(column_categories);
        err_code_ = init();
    }

    /**
     * @brief Constructs a Tablet object with the given parameters.
     *
     * @param column_names A vector containing the names of the columns in the
     * tablet. Each name corresponds to a column in the target table.
     * @param data_types A vector containing the data types of each column.
     *                   These must match the schema of the target table.
     * @param max_rows The maximum number of rows that this tablet can hold.
     * Defaults to DEFAULT_MAX_ROWS.
     */
    Tablet(const std::vector<std::string>& column_names,
           const std::vector<common::TSDataType>& data_types,
           uint32_t max_rows = DEFAULT_MAX_ROWS)
        : max_row_num_(max_rows),
          cur_row_size_(0),
          timestamps_(nullptr),
          value_matrix_(nullptr),
          bitmaps_(nullptr) {
        schema_vec_ = std::make_shared<std::vector<MeasurementSchema>>();
        for (size_t i = 0; i < column_names.size(); i++) {
            schema_vec_->emplace_back(column_names[i], data_types[i],
                                      common::get_value_encoder(data_types[i]),
                                      common::get_default_compressor());
        }
        err_code_ = init();
    }

    ~Tablet() { destroy(); }

    const std::string& get_table_name() const { return insert_target_name_; }
    void set_table_name(const std::string& table_name) {
        insert_target_name_ = table_name;
    }
    size_t get_column_count() const { return schema_vec_->size(); }
    uint32_t get_cur_row_size() const { return cur_row_size_; }

    /**
     * @brief Adds a timestamp to the specified row.
     *
     * @param row_index The index of the row to which the timestamp will be
     * added. Must be less than the maximum number of rows.
     * @param timestamp The timestamp value to add.
     * @return Returns 0 on success, or a non-zero error code on failure.
     */
    int add_timestamp(uint32_t row_index, int64_t timestamp);

    int set_timestamps(const int64_t* timestamps, uint32_t count);

    // Bulk copy fixed-length column data. bitmap=nullptr means all non-null.
    // bitmap uses TsFile convention: bit=1 is null, bit=0 is valid.
    int set_column_values(uint32_t schema_index, const void* data,
                          const uint8_t* bitmap, uint32_t count);

    // Bulk fill a STRING column with the same value for all rows.
    int set_column_string_repeated(uint32_t schema_index, const char* str,
                                   uint32_t str_len, uint32_t count);

    // Reset per-batch state so the tablet can be reused without reallocating
    // its backing buffers. row_count is typically 0 before refilling.
    void reset(uint32_t row_count = 0);

    void* get_value(int row_index, uint32_t schema_index,
                    common::TSDataType& data_type) const;
    /**
     * @brief Template function to add a value of type T to the specified row
     * and column.
     *
     * @tparam T The type of the value to add.
     * @param row_index The index of the row to which the value will be added.
     *                  Must be less than the maximum number of rows.
     * @param schema_index The index of the column schema corresponding to the
     * value being added.
     * @param val The value to add.
     * @return Returns 0 on success, or a non-zero error code on failure.
     */
    template <typename T>
    int add_value(uint32_t row_index, uint32_t schema_index, T val);

    void set_column_categories(
        const std::vector<common::ColumnCategory>& column_categories);
    std::shared_ptr<IDeviceID> get_device_id(int i) const;
    std::vector<uint32_t> find_all_device_boundaries() const;

    // When the caller guarantees that all rows belong to a single device,
    // set this flag to skip the O(n*m) boundary detection in the write path.
    void set_single_device(bool v) { single_device_ = v; }
    bool is_single_device() const { return single_device_; }
    /**
     * @brief Template function to add a value of type T to the specified row
     * and column by name.
     *
     * @tparam T The type of the value to add.
     * @param row_index The index of the row to which the value will be added.
     *                  Must be less than the maximum number of rows.
     * @param measurement_name The name of the column to which the value will be
     * added. Must match one of the column names provided during construction.
     * @param val The value to add.
     * @return Returns 0 on success, or a non-zero error code on failure.
     */
    template <typename T>
    int add_value(uint32_t row_index, const std::string& measurement_name,
                  T val);

    FORCE_INLINE const std::string& get_column_name(
        uint32_t column_index) const {
        return schema_vec_->at(column_index).measurement_name_;
    }

    void set_column_name(uint32_t column_index, const std::string& name) {
        schema_vec_->at(column_index).measurement_name_ = name;
    }

    const std::map<std::string, int>& get_schema_map() const {
        return schema_map_;
    }

    void set_schema_map(const std::map<std::string, int>& schema_map) {
        schema_map_ = schema_map;
    }

    void reset_string_columns();

    friend class TabletColIterator;
    friend class TsFileWriter;
    friend struct MeasurementNamesFromTablet;

   private:
    typedef std::map<std::string, int>::iterator SchemaMapIterator;
    int init();
    void destroy();

   private:
    template <typename T>
    void process_val(uint32_t row_index, uint32_t schema_index, T val);
    uint32_t max_row_num_;
    uint32_t cur_row_size_;
    std::string insert_target_name_;
    std::shared_ptr<std::vector<MeasurementSchema>> schema_vec_;
    std::map<std::string, int> schema_map_;
    int64_t* timestamps_;
    ValueMatrixEntry* value_matrix_;
    common::BitMap* bitmaps_;
    std::vector<common::ColumnCategory> column_categories_;
    std::vector<int> id_column_indexes_;
    bool single_device_ = false;
};

}  // end namespace storage
#endif  // COMMON_TABLET_H
