/*
 * 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 {
        int32_t* offsets;       // length: max_rows + 1 (Arrow-compatible)
        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 = (int32_t*)common::mem_alloc(
                sizeof(int32_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;
            this->~StringColumn();
        }

        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] = static_cast<int32_t>(buf_used);
            offsets[row + 1] = static_cast<int32_t>(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(); }

    // Tablet owns several heap buffers (timestamps_, value_matrix_ with its
    // StringColumn::buffer/offsets, bitmaps_) that ~Tablet frees. The default
    // copy ctor / copy-assign shallow-copies the raw pointers, so any copy
    // path (e.g. `return tablet;` without NRVO under MSVC Debug) leaves the
    // source Tablet's destructor freeing buffers the copy still points at,
    // triggering heap-use-after-free in code like
    // Tablet::find_all_device_boundaries. Make Tablet move-only with a
    // pointer-stealing move ctor / move-assign so return-by-value is safe.
    Tablet(const Tablet&) = delete;
    Tablet& operator=(const Tablet&) = delete;

    Tablet(Tablet&& other) noexcept
        : err_code_(other.err_code_),
          max_row_num_(other.max_row_num_),
          cur_row_size_(other.cur_row_size_),
          insert_target_name_(std::move(other.insert_target_name_)),
          schema_vec_(std::move(other.schema_vec_)),
          schema_map_(std::move(other.schema_map_)),
          timestamps_(other.timestamps_),
          value_matrix_(other.value_matrix_),
          bitmaps_(other.bitmaps_),
          column_categories_(std::move(other.column_categories_)),
          id_column_indexes_(std::move(other.id_column_indexes_)),
          single_device_(other.single_device_) {
        other.timestamps_ = nullptr;
        other.value_matrix_ = nullptr;
        other.bitmaps_ = nullptr;
        other.cur_row_size_ = 0;
        // Leaving other.schema_vec_ moved-from is fine; destroy() only
        // touches the heap buffers above, which we've now nulled out.
    }

    Tablet& operator=(Tablet&& other) noexcept {
        if (this != &other) {
            destroy();
            err_code_ = other.err_code_;
            max_row_num_ = other.max_row_num_;
            cur_row_size_ = other.cur_row_size_;
            insert_target_name_ = std::move(other.insert_target_name_);
            schema_vec_ = std::move(other.schema_vec_);
            schema_map_ = std::move(other.schema_map_);
            timestamps_ = other.timestamps_;
            value_matrix_ = other.value_matrix_;
            bitmaps_ = other.bitmaps_;
            column_categories_ = std::move(other.column_categories_);
            id_column_indexes_ = std::move(other.id_column_indexes_);
            single_device_ = other.single_device_;
            other.timestamps_ = nullptr;
            other.value_matrix_ = nullptr;
            other.bitmaps_ = nullptr;
            other.cur_row_size_ = 0;
        }
        return *this;
    }

    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 copy a STRING column from Arrow-style offsets + flat data buffer.
    // bitmap=nullptr means all non-null; same convention as set_column_values.
    int set_column_string_values(uint32_t schema_index, const int32_t* offsets,
                                 const char* 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
