/*
 * 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_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);
    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::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) {
    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;
    }

    if (table_query_executor_ == nullptr) {
        table_query_executor_ = new TableQueryExecutor(read_file_);
    }
    ret = table_query_executor_->query(to_lower(table_name), column_names,
                                       /*time_filter=*/nullptr,
                                       /*tag_filter=*/nullptr,
                                       /*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);
    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 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) {
            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
