/*
 * 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 "tsfile_reader.h"

#include "common/schema.h"
#include "filter/time_operator.h"
#include "tsfile_executor.h"

using namespace common;
using namespace storage;

namespace {

struct DeviceMetaEntry {
    std::shared_ptr<IDeviceID> device_id;
    int64_t start_offset;
    int64_t end_offset;
};

int get_all_device_entries(std::vector<DeviceMetaEntry>& entries,
                           std::shared_ptr<MetaIndexNode> index_node,
                           ReadFile* read_file, PageArena& pa) {
    int ret = E_OK;
    if (index_node == nullptr) {
        return ret;
    }
    if (index_node->node_type_ == LEAF_DEVICE) {
        for (size_t i = 0; i < index_node->children_.size(); i++) {
            DeviceMetaEntry entry;
            entry.device_id = index_node->children_[i]->get_device_id();
            entry.start_offset = index_node->children_[i]->get_offset();
            entry.end_offset = (i + 1 < index_node->children_.size())
                                   ? index_node->children_[i + 1]->get_offset()
                                   : index_node->end_offset_;
            entries.push_back(entry);
        }
    } else {
        for (size_t idx = 0; idx < index_node->children_.size(); idx++) {
            auto meta_index_entry = index_node->children_[idx];
            int64_t start_offset = meta_index_entry->get_offset();
            int64_t end_offset = index_node->end_offset_;
            if (idx + 1 < index_node->children_.size()) {
                end_offset = index_node->children_[idx + 1]->get_offset();
            }
            ASSERT(end_offset - start_offset > 0);
            const int32_t read_size = (int32_t)(end_offset - start_offset);
            int32_t ret_read_len = 0;
            char* data_buf = (char*)pa.alloc(read_size);
            void* m_idx_node_buf = pa.alloc(sizeof(MetaIndexNode));
            if (IS_NULL(data_buf) || IS_NULL(m_idx_node_buf)) {
                return E_OOM;
            }
            auto* top_node_ptr = new (m_idx_node_buf) MetaIndexNode(&pa);
            auto top_node = std::shared_ptr<MetaIndexNode>(
                top_node_ptr, [](MetaIndexNode* ptr) {
                    if (ptr) {
                        ptr->~MetaIndexNode();
                    }
                });
            if (RET_FAIL(read_file->read(start_offset, data_buf, read_size,
                                         ret_read_len))) {
            } else if (RET_FAIL(top_node->device_deserialize_from(data_buf,
                                                                  read_size))) {
            } else {
                ret = get_all_device_entries(entries, top_node, read_file, pa);
            }
            if (ret != E_OK) {
                return ret;
            }
        }
    }
    return ret;
}

}  // namespace

namespace storage {
TsFileReader::TsFileReader()
    : read_file_(nullptr),
      tsfile_executor_(nullptr),
      table_query_executor_(nullptr) {
    tsfile_reader_meta_pa_.init(512, MOD_TSFILE_READER);
}

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

int TsFileReader::open(const std::string& file_path) {
    int ret = E_OK;
    read_file_ = new storage::ReadFile;
    tsfile_executor_ = new storage::TsFileExecutor();
    if (RET_FAIL(read_file_->open(file_path))) {
        std::cout << "filed to open file " << ret << std::endl;
    } else if (RET_FAIL(tsfile_executor_->init(read_file_))) {
        std::cout << "filed to init " << ret << std::endl;
    }
    return ret;
}

int TsFileReader::ensure_table_query_executor(int batch_size) {
    if (table_query_executor_ != nullptr &&
        table_query_executor_batch_size_ == batch_size) {
        return E_OK;
    }

    if (table_query_executor_ != nullptr) {
        delete table_query_executor_;
        table_query_executor_ = nullptr;
    }

    table_query_executor_ = new TableQueryExecutor(read_file_, batch_size);
    table_query_executor_batch_size_ = batch_size;
    return E_OK;
}

int TsFileReader::close() {
    int ret = E_OK;
    if (tsfile_executor_ != nullptr) {
        delete tsfile_executor_;
        tsfile_executor_ = nullptr;
    }
    if (table_query_executor_ != nullptr) {
        delete table_query_executor_;
        table_query_executor_ = nullptr;
    }
    if (read_file_ != nullptr) {
        read_file_->close();
        delete read_file_;
        read_file_ = nullptr;
    }
    return ret;
}

int TsFileReader::query(QueryExpression* qe, ResultSet*& ret_qds) {
    return tsfile_executor_->execute(qe, ret_qds);
}

int TsFileReader::query(std::vector<std::string>& path_list, int64_t start_time,
                        int64_t end_time, ResultSet*& result_set) {
    int ret = E_OK;
    Filter* time_filter = new TimeBetween(start_time, end_time, false);
    Expression* exp =
        new storage::Expression(storage::GLOBALTIME_EXPR, time_filter);
    std::vector<Path> path_list_vec;
    for (const auto& path : path_list) {
        path_list_vec.emplace_back(Path(path, true));
    }
    QueryExpression* query_expression =
        QueryExpression::create(path_list_vec, exp);
    ret = tsfile_executor_->execute(query_expression, result_set);
    return ret;
}

int TsFileReader::query(const std::string& table_name,
                        const std::vector<std::string>& columns_names,
                        int64_t start_time, int64_t end_time,
                        ResultSet*& result_set, int batch_size) {
    return this->query(table_name, columns_names, start_time, end_time,
                       result_set, nullptr, batch_size);
}

int TsFileReader::query(const std::string& table_name,
                        const std::vector<std::string>& columns_names,
                        int64_t start_time, int64_t end_time,
                        ResultSet*& result_set, Filter* tag_filter,
                        int batch_size) {
    int ret = E_OK;
    TsFileMeta* tsfile_meta = tsfile_executor_->get_tsfile_meta();
    if (tsfile_meta == nullptr) {
        return E_FILE_READ_ERR;
    }
    std::shared_ptr<TableSchema> table_schema =
        tsfile_meta->table_schemas_.at(to_lower(table_name));
    if (table_schema == nullptr) {
        return E_TABLE_NOT_EXIST;
    }

    Filter* time_filter = new TimeBetween(start_time, end_time, false);
    ensure_table_query_executor(batch_size);
    ret = table_query_executor_->query(to_lower(table_name), columns_names,
                                       time_filter, tag_filter, nullptr,
                                       result_set);
    return ret;
}

int TsFileReader::queryByRow(std::vector<std::string>& path_list, int offset,
                             int limit, ResultSet*& result_set) {
    int ret = E_OK;
    std::vector<Path> path_list_vec;
    for (const auto& path : path_list) {
        path_list_vec.emplace_back(Path(path, true));
    }
    QueryExpression* query_expression =
        QueryExpression::create(path_list_vec, nullptr);
    ret =
        tsfile_executor_->execute(query_expression, result_set, offset, limit);
    return ret;
}

int TsFileReader::queryByRow(const std::string& table_name,
                             const std::vector<std::string>& column_names,
                             int offset, int limit, ResultSet*& result_set,
                             Filter* tag_filter, int batch_size) {
    int ret = E_OK;
    TsFileMeta* tsfile_meta = tsfile_executor_->get_tsfile_meta();
    if (tsfile_meta == nullptr) {
        return E_FILE_READ_ERR;
    }
    auto it = tsfile_meta->table_schemas_.find(to_lower(table_name));
    if (it == tsfile_meta->table_schemas_.end() || it->second == nullptr) {
        return E_TABLE_NOT_EXIST;
    }

    ensure_table_query_executor(batch_size);
    ret = table_query_executor_->query(to_lower(table_name), column_names,
                                       /*time_filter=*/nullptr, tag_filter,
                                       /*field_filter=*/nullptr, offset, limit,
                                       result_set);
    return ret;
}

int TsFileReader::query_table_on_tree(
    const std::vector<std::string>& measurement_names, int64_t star_time,
    int64_t end_time, ResultSet*& result_set) {
    int ret = E_OK;
    TsFileMeta* tsfile_meta = tsfile_executor_->get_tsfile_meta();
    if (tsfile_meta == nullptr) {
        return E_FILE_READ_ERR;
    }
    auto device_ids = this->get_all_device_ids();
    std::vector<std::shared_ptr<IDeviceID>> satisfied_device_ids;
    std::unordered_set<std::string> measurement_names_set_to_query;
    size_t device_max_len = 0;

    if (measurement_names.empty()) {
        for (auto& device_name : device_ids) {
            std::vector<MeasurementSchema> schemas;
            this->get_timeseries_schema(device_name, schemas);
            satisfied_device_ids.push_back(device_name);
            for (auto& schema : schemas) {
                measurement_names_set_to_query.insert(schema.measurement_name_);
            }
            device_name->split_table_name();
            if (device_name->get_split_seg_num() > device_max_len) {
                device_max_len = device_name->get_split_seg_num();
            }
        }
    } else {
        std::unordered_set<std::string> found_measurement_names;
        std::unordered_set<std::string> required_measurement_names(
            measurement_names.begin(), measurement_names.end());
        for (auto& device_name : device_ids) {
            std::vector<MeasurementSchema> schemas;
            this->get_timeseries_schema(device_name, schemas);

            bool device_has_required_measurement_names = false;
            for (auto& schema : schemas) {
                if (required_measurement_names.find(schema.measurement_name_) !=
                    required_measurement_names.end()) {
                    found_measurement_names.insert(schema.measurement_name_);
                    device_has_required_measurement_names = true;
                }
            }
            if (device_has_required_measurement_names) {
                device_name->split_table_name();
                satisfied_device_ids.push_back(device_name);
                if (device_name->get_split_seg_num() > device_max_len) {
                    device_max_len = device_name->get_split_seg_num();
                }
            }
        }

        if (found_measurement_names.size() <
            required_measurement_names.size()) {
            return E_COLUMN_NOT_EXIST;
        }
        measurement_names_set_to_query = found_measurement_names;
    }
    std::vector<std::string> measurement_names_to_query;
    // Get all columns.
    if (measurement_names.empty() && !measurement_names_set_to_query.empty()) {
        for (auto& measurement_name : measurement_names_set_to_query) {
            measurement_names_to_query.push_back(measurement_name);
        }
    } else {
        measurement_names_to_query = measurement_names;
    }
    std::vector<std::string> columns_names(device_max_len);
    for (int i = 0; i < device_max_len; i++) {
        columns_names[i] = "col_" + std::to_string(i);
    }
    Filter* time_filter = new TimeBetween(star_time, end_time, false);
    ensure_table_query_executor(-1);
    ret = table_query_executor_->query_on_tree(
        satisfied_device_ids, columns_names, measurement_names_to_query,
        time_filter, result_set);
    return ret;
}

void TsFileReader::destroy_query_data_set(storage::ResultSet* qds) {
    tsfile_executor_->destroy_query_data_set(qds);
}

std::vector<std::shared_ptr<IDeviceID>> TsFileReader::get_all_devices(
    std::string table_name) {
    TsFileMeta* tsfile_meta = tsfile_executor_->get_tsfile_meta();
    std::vector<std::shared_ptr<IDeviceID>> device_ids;
    if (tsfile_meta != nullptr) {
        PageArena pa;
        pa.init(512, MOD_TSFILE_READER);
        to_lowercase_inplace(table_name);
        auto it = tsfile_meta->table_metadata_index_node_map_.find(table_name);
        if (it != tsfile_meta->table_metadata_index_node_map_.end() &&
            it->second != nullptr) {
            get_all_devices(device_ids, it->second, pa);
        }
    }
    return device_ids;
}

std::vector<std::shared_ptr<IDeviceID>> TsFileReader::get_all_device_ids() {
    TsFileMeta* tsfile_meta = tsfile_executor_->get_tsfile_meta();
    std::vector<std::shared_ptr<IDeviceID>> device_ids;
    if (tsfile_meta != nullptr) {
        PageArena pa;
        pa.init(512, MOD_TSFILE_READER);
        for (auto entry : tsfile_meta->table_metadata_index_node_map_) {
            auto index_node = entry.second;
            get_all_devices(device_ids, index_node, pa);
        }
    }
    return device_ids;
}

std::vector<std::shared_ptr<IDeviceID>> TsFileReader::get_all_devices() {
    return get_all_device_ids();
}

int TsFileReader::get_all_devices(
    std::vector<std::shared_ptr<IDeviceID>>& device_ids,
    std::shared_ptr<MetaIndexNode> index_node, PageArena& pa) {
    int ret = E_OK;
    if (index_node != nullptr) {
        if (index_node->node_type_ == LEAF_DEVICE) {
            for (const auto& meta_index_entry : index_node->children_) {
                device_ids.push_back(meta_index_entry->get_device_id());
            }
        } else {
            for (size_t idx = 0; idx < index_node->children_.size(); idx++) {
                auto meta_index_entry = index_node->children_[idx];
                int start_offset = meta_index_entry->get_offset();
                int end_offset = index_node->end_offset_;
                if (idx + 1 < index_node->children_.size()) {
                    end_offset = index_node->children_[idx + 1]->get_offset();
                }
                ASSERT(end_offset - start_offset > 0);
                const int32_t read_size = (int32_t)end_offset - start_offset;
                int32_t ret_read_len = 0;
                char* data_buf = (char*)pa.alloc(read_size);
                void* m_idx_node_buf = pa.alloc(sizeof(MetaIndexNode));
                if (IS_NULL(data_buf) || IS_NULL(m_idx_node_buf)) {
                    return E_OOM;
                }
                auto* top_node_ptr = new (m_idx_node_buf) MetaIndexNode(&pa);
                auto top_node = std::shared_ptr<MetaIndexNode>(
                    top_node_ptr, [](MetaIndexNode* ptr) {
                        if (ptr) {
                            ptr->~MetaIndexNode();
                        }
                    });

                if (RET_FAIL(read_file_->read(start_offset, data_buf, read_size,
                                              ret_read_len))) {
                } else if (RET_FAIL(top_node->device_deserialize_from(
                               data_buf, read_size))) {
                } else {
                    ret = get_all_devices(device_ids, top_node, pa);
                }
            }
        }
    }
    return ret;
}

int TsFileReader::get_timeseries_schema(
    std::shared_ptr<IDeviceID> device_id,
    std::vector<MeasurementSchema>& result) {
    int ret = E_OK;
    std::vector<ITimeseriesIndex*> timeseries_indexs;
    PageArena pa;
    pa.init(512, MOD_TSFILE_READER);
    if (RET_FAIL(tsfile_executor_->get_tsfile_io_reader()
                     ->get_device_timeseries_meta_without_chunk_meta(
                         device_id, timeseries_indexs, pa))) {
    } else {
        for (auto timeseries_index : timeseries_indexs) {
            // AlignedTimeseriesIndex::get_data_type() returns the time
            // column type (VECTOR) so the aligned/non-aligned dispatch in
            // SSI can keep using the existing accessor.  For schema
            // exposure we need the actual value column type — without this
            // unwrap, INT32/FLOAT/... would all surface as VECTOR.
            common::TSDataType dt = timeseries_index->get_data_type();
            if (dt == common::VECTOR) {
                auto* aligned =
                    dynamic_cast<AlignedTimeseriesIndex*>(timeseries_index);
                if (aligned != nullptr && aligned->value_ts_idx_ != nullptr) {
                    dt = aligned->value_ts_idx_->get_data_type();
                }
            }
            MeasurementSchema ms(
                timeseries_index->get_measurement_name().to_std_string(), dt);
            result.push_back(ms);
        }
    }
    return E_OK;
}

int TsFileReader::get_timeseries_metadata_impl(
    std::shared_ptr<IDeviceID> device_id,
    std::vector<std::shared_ptr<ITimeseriesIndex>>& result) {
    int ret = E_OK;
    std::vector<ITimeseriesIndex*> timeseries_indexs;
    auto noop_deleter = [](ITimeseriesIndex*) {};
    if (RET_FAIL(
            tsfile_executor_->get_tsfile_io_reader()
                ->get_device_timeseries_meta_without_chunk_meta(
                    device_id, timeseries_indexs, tsfile_reader_meta_pa_))) {
    } else {
        for (auto timeseries_index : timeseries_indexs) {
            result.emplace_back(std::shared_ptr<ITimeseriesIndex>(
                timeseries_index, noop_deleter));
        }
    }
    return ret;
}

DeviceTimeseriesMetadataMap TsFileReader::get_timeseries_metadata(
    const std::vector<std::shared_ptr<IDeviceID>>& device_ids) {
    // Reset the shared meta arena up front: every call writes fresh
    // timeseries-index metadata into it via _impl(), and the previous
    // implementation only ever appended.  A long-lived reader that repeats
    // this query would grow tsfile_reader_meta_pa_ without bound (each call
    // duplicates the per-device payload).  Callers that need to retain prior
    // results past this call must copy them out before invoking again — the
    // shared_ptrs handed back use a noop deleter pointing into this arena.
    tsfile_reader_meta_pa_.destroy();
    tsfile_reader_meta_pa_.init(512, MOD_TSFILE_READER);
    DeviceTimeseriesMetadataMap result;
    for (const auto& device_id : device_ids) {
        std::vector<std::shared_ptr<ITimeseriesIndex>> list;
        if (get_timeseries_metadata_impl(device_id, list) == E_OK) {
            result.insert(std::make_pair(device_id, std::move(list)));
        }
        // Skip non-existent devices (not inserted)
    }
    return result;
}

DeviceTimeseriesMetadataMap TsFileReader::get_timeseries_metadata() {
    DeviceTimeseriesMetadataMap result;
    TsFileMeta* tsfile_meta = tsfile_executor_->get_tsfile_meta();
    if (tsfile_meta == nullptr) {
        return result;
    }

    // Same arena-reset rationale as the device_ids overload above.
    tsfile_reader_meta_pa_.destroy();
    tsfile_reader_meta_pa_.init(512, MOD_TSFILE_READER);

    PageArena pa;
    pa.init(512, MOD_TSFILE_READER);
    std::vector<DeviceMetaEntry> entries;
    for (auto& table_entry : tsfile_meta->table_metadata_index_node_map_) {
        if (get_all_device_entries(entries, table_entry.second, read_file_,
                                   pa) != E_OK) {
            return result;
        }
    }

    auto noop_deleter = [](ITimeseriesIndex*) {};
    for (auto& device_entry : entries) {
        std::vector<ITimeseriesIndex*> raw_ts_indexes;
        if (tsfile_executor_->get_tsfile_io_reader()
                ->get_device_timeseries_meta_by_offset(
                    device_entry.start_offset, device_entry.end_offset,
                    raw_ts_indexes, tsfile_reader_meta_pa_) == E_OK) {
            std::vector<std::shared_ptr<ITimeseriesIndex>> list;
            for (auto ts_idx : raw_ts_indexes) {
                list.emplace_back(
                    std::shared_ptr<ITimeseriesIndex>(ts_idx, noop_deleter));
            }
            result.insert(
                std::make_pair(device_entry.device_id, std::move(list)));
        }
    }
    return result;
}

ResultSet* TsFileReader::read_timeseries(
    const std::shared_ptr<IDeviceID>& device_id,
    const std::vector<std::string>& measurement_name) {
    return nullptr;
}

std::shared_ptr<TableSchema> TsFileReader::get_table_schema(
    const std::string& table_name) {
    TsFileMeta* file_metadata = tsfile_executor_->get_tsfile_meta();
    MetaIndexNode* table_root = nullptr;
    std::shared_ptr<TableSchema> table_schema;
    if (IS_FAIL(file_metadata->get_table_metaindex_node(to_lower(table_name),
                                                        table_root))) {
    } else if (IS_FAIL(file_metadata->get_table_schema(to_lower(table_name),
                                                       table_schema))) {
    }
    return table_schema;
}

std::vector<std::shared_ptr<TableSchema>>
TsFileReader::get_all_table_schemas() {
    TsFileMeta* file_metadata = tsfile_executor_->get_tsfile_meta();
    std::vector<std::shared_ptr<TableSchema>> table_schemas;
    for (const auto& table_schema : file_metadata->table_schemas_) {
        table_schemas.push_back(table_schema.second);
    }
    return table_schemas;
}

}  // namespace storage
