/*
 * 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 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::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_TSFILE_WRITER_META_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);
    if (table_query_executor_ == nullptr) {
        table_query_executor_ = new TableQueryExecutor(read_file_, batch_size);
    }
    ret = table_query_executor_->query(to_lower(table_name), columns_names,
                                       time_filter, tag_filter, nullptr,
                                       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_TSFILE_WRITER_META_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);
    if (table_query_executor_ == nullptr) {
        table_query_executor_ = new TableQueryExecutor(read_file_);
    }
    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 index_node =
            tsfile_meta->table_metadata_index_node_map_[table_name];
        get_all_devices(device_ids, index_node, 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) {
            MeasurementSchema ms(
                timeseries_index->get_measurement_name().to_std_string(),
                timeseries_index->get_data_type());
            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;
    tsfile_reader_meta_pa_.init(512, MOD_TSFILE_READER);
    // Pointers are owned by tsfile_reader_meta_pa_; shared_ptr must not delete
    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) {
    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() {
    // Collect metadata for all devices present in the file
    DeviceTimeseriesMetadataMap result;
    auto device_ids = get_all_device_ids();
    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)));
        }
    }
    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
