/*
 * 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.
 */
#include "reader/table_result_set.h"

#include <utils/storage_utils.h>

#include <cstring>

namespace storage {
void TableResultSet::init() {
    row_record_ = new RowRecord(column_names_.size() + 1);
    pa_.reset();
    pa_.init(512, common::MOD_TSFILE_READER);
    index_lookup_.reserve(column_names_.size() + 1);
    index_lookup_.insert({"time", 0});
    for (uint32_t i = 0; i < column_names_.size(); ++i) {
        index_lookup_.insert({column_names_[i], i + 1});
    }
    result_set_metadata_ =
        std::make_shared<ResultSetMetadata>(column_names_, data_types_);
}

TableResultSet::~TableResultSet() { close(); }

int TableResultSet::next(bool& has_next) {
    if (return_mode_ != RETURN_ROW) {
        return tsblock_reader_->has_next(has_next);
    }

    int ret = common::E_OK;

    // Advance past the row yielded by the previous next() call, if any.
    // Row iterator's next() advances all per-column offsets, so on the next
    // read the vectors point to the new row's data.
    if (row_ready_) {
        row_iterator_->next();
        row_ready_ = false;
        row_materialized_ = false;
    }

    // Find the next non-empty TsBlock.
    while (row_iterator_ == nullptr || !row_iterator_->has_next()) {
        if (RET_FAIL(tsblock_reader_->has_next(has_next))) {
            return ret;
        }

        if (!has_next) {
            if (row_iterator_) {
                delete row_iterator_;
                row_iterator_ = nullptr;
            }
            break;
        }

        if (RET_FAIL(tsblock_reader_->next(tsblock_))) {
            break;
        }
        if (row_iterator_) {
            delete row_iterator_;
            row_iterator_ = nullptr;
        }

        row_iterator_ = new common::RowIterator(tsblock_);
    }
    if (row_iterator_ == nullptr || !row_iterator_->has_next()) {
        has_next = false;
        return ret;
    }

    // A row is now available at row_iterator_'s current row_id_; the per-
    // column vector offsets are pointing at that row's data.  We do NOT
    // populate row_record_ here — typed accessors read straight from the
    // vectors, and get_row_record() lazily materializes on demand.
    has_next = true;
    row_ready_ = true;
    return ret;
}

void TableResultSet::materialize_current_row() {
    uint32_t len = 0;
    bool null = false;
    row_record_->reset();
    for (uint32_t i = 0; i < row_iterator_->get_column_count(); ++i) {
        const auto value = row_iterator_->read(i, &len, &null);
        if (!null) {
            row_record_->get_field(i)->set_value(
                row_iterator_->get_data_type(i), value, len, pa_);
        }
    }
}

bool TableResultSet::is_null(const std::string& column_name) {
    auto iter = index_lookup_.find(column_name);
    if (iter == index_lookup_.end()) {
        return true;
    } else {
        return is_null(iter->second + 1);
    }
}

bool TableResultSet::is_null(uint32_t column_index) {
    ASSERT(1 <= column_index && column_index <= row_record_->get_col_num());
    if (!row_ready_) return true;
    return row_iterator_->is_null_at(column_index - 1);
}

// Direct buffer access — skips Vector::read's virtual dispatch.  Caller is
// expected to have checked is_null() (we still null-guard for safety).
// For fixed-width primitives the vector keeps its value buffer in
// values_ and tracks the current row's byte offset in offset_; the
// element at the active row is simply *(T*)(values_.get_data() + offset_).
// The ASSERT enforces strict typed access: the requested C++ type must match
// the column's physical storage width (DATE is int32, not int64).  On a
// mismatch it fires in debug instead of silently splicing the adjacent cell's
// bytes into the result.
#define TSFILE_FAST_PRIMITIVE_READ(TYPE, DFLT)                                \
    if (!row_ready_) return DFLT;                                             \
    common::Vector* vec = row_iterator_->get_vector(column_index - 1);        \
    ASSERT(common::TypeMatch<TYPE>(vec->get_vector_type()));                  \
    if (vec->has_null() && vec->is_null(row_iterator_->get_row_id()))         \
        return DFLT;                                                          \
    TYPE value;                                                               \
    std::memcpy(&value, vec->get_value_data().get_data() + vec->get_offset(), \
                sizeof(value));                                               \
    return value

bool TableResultSet::get_bool_at(uint32_t column_index) {
    TSFILE_FAST_PRIMITIVE_READ(bool, false);
}

int32_t TableResultSet::get_int32_at(uint32_t column_index) {
    TSFILE_FAST_PRIMITIVE_READ(int32_t, 0);
}

int64_t TableResultSet::get_int64_at(uint32_t column_index) {
    TSFILE_FAST_PRIMITIVE_READ(int64_t, 0);
}

float TableResultSet::get_float_at(uint32_t column_index) {
    TSFILE_FAST_PRIMITIVE_READ(float, 0.0f);
}

double TableResultSet::get_double_at(uint32_t column_index) {
    TSFILE_FAST_PRIMITIVE_READ(double, 0.0);
}

#undef TSFILE_FAST_PRIMITIVE_READ

RowRecord* TableResultSet::get_row_record() {
    if (row_ready_ && !row_materialized_) {
        materialize_current_row();
        row_materialized_ = true;
    }
    return row_record_;
}

std::shared_ptr<ResultSetMetadata> TableResultSet::get_metadata() {
    return result_set_metadata_;
}

int TableResultSet::get_next_tsblock(common::TsBlock*& block) {
    int ret = common::E_OK;
    block = nullptr;

    if (return_mode_ == RETURN_ROW) {
        return common::E_INVALID_ARG;
    }

    bool has_next = false;
    if (RET_FAIL(tsblock_reader_->has_next(has_next))) {
        return ret;
    }

    if (!has_next) {
        return common::E_NO_MORE_DATA;
    }

    if (RET_FAIL(tsblock_reader_->next(tsblock_))) {
        return ret;
    }

    if (tsblock_ == nullptr) {
        return common::E_NO_MORE_DATA;
    }

    block = tsblock_;
    return common::E_OK;
}

void TableResultSet::close() {
    if (closed_) {
        return;
    }
    closed_ = true;
    if (tsblock_reader_) {
        tsblock_reader_->close();
    }
    pa_.destroy();
    if (row_record_) {
        delete row_record_;
        row_record_ = nullptr;
    }
    if (row_iterator_) {
        delete row_iterator_;
        row_iterator_ = nullptr;
    }
}

}  // namespace storage
