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

#include "utils/db_utils.h"

namespace storage {
int TableQueryExecutor::query(const std::string& table_name,
                              const std::vector<std::string>& columns,
                              Filter* time_filter, Filter* tag_filter,
                              Filter* field_filter, ResultSet*& ret_qds) {
    int ret = common::E_OK;
    TsFileMeta* file_metadata = nullptr;
    file_metadata = tsfile_io_reader_->get_tsfile_meta();
    common::PageArena pa;
    pa.init(512, common::MOD_TSFILE_READER);
    MetaIndexNode* table_root = nullptr;
    std::shared_ptr<TableSchema> table_schema;
    if (RET_FAIL(
            file_metadata->get_table_metaindex_node(table_name, table_root))) {
    } else if (RET_FAIL(
                   file_metadata->get_table_schema(table_name, table_schema))) {
    }

    if (IS_FAIL(ret)) {
        ret_qds = nullptr;
        delete time_filter;
        return ret;
    }
    std::vector<std::string> lower_case_column_names(columns);
    for (auto& column : lower_case_column_names) {
        to_lowercase_inplace(column);
    }
    std::shared_ptr<ColumnMapping> column_mapping =
        std::make_shared<ColumnMapping>();
    for (size_t i = 0; i < lower_case_column_names.size(); ++i) {
        column_mapping->add(lower_case_column_names[i], static_cast<int>(i),
                            *table_schema);
    }
    std::vector<common::TSDataType> data_types;
    data_types.reserve(lower_case_column_names.size());
    for (size_t i = 0; i < lower_case_column_names.size(); ++i) {
        auto ind = table_schema->find_column_index(lower_case_column_names[i]);
        if (ind < 0) {
            delete time_filter;
            return common::E_COLUMN_NOT_EXIST;
        }
        data_types.push_back(table_schema->get_data_types()[ind]);
    }
    // column_mapping.add(*measurement_filter);

    auto device_task_iterator =
        std::unique_ptr<DeviceTaskIterator>(new DeviceTaskIterator(
            lower_case_column_names, table_root, column_mapping,
            meta_data_querier_, tag_filter, table_schema));

    std::unique_ptr<TsBlockReader> tsblock_reader;
    switch (table_query_ordering_) {
        case TableQueryOrdering::DEVICE:
            tsblock_reader = std::unique_ptr<DeviceOrderedTsBlockReader>(
                new DeviceOrderedTsBlockReader(
                    std::move(device_task_iterator), meta_data_querier_,
                    block_size_, tsfile_io_reader_, time_filter, field_filter));
            break;
        case TableQueryOrdering::TIME:
        default:
            delete time_filter;
            ret_qds = nullptr;
            return common::E_UNSUPPORTED_ORDER;
    }
    assert(tsblock_reader != nullptr);
    ret_qds =
        new TableResultSet(std::move(tsblock_reader), lower_case_column_names,
                           data_types, return_mode_);
    return ret;
}

int TableQueryExecutor::query(const std::string& table_name,
                              const std::vector<std::string>& columns,
                              Filter* time_filter, Filter* tag_filter,
                              Filter* field_filter, int offset, int limit,
                              ResultSet*& ret_qds) {
    int ret = common::E_OK;
    TsFileMeta* file_metadata = nullptr;
    file_metadata = tsfile_io_reader_->get_tsfile_meta();
    common::PageArena pa;
    pa.init(512, common::MOD_TSFILE_READER);
    MetaIndexNode* table_root = nullptr;
    std::shared_ptr<TableSchema> table_schema;
    if (RET_FAIL(
            file_metadata->get_table_metaindex_node(table_name, table_root))) {
    } else if (RET_FAIL(
                   file_metadata->get_table_schema(table_name, table_schema))) {
    }

    if (IS_FAIL(ret)) {
        ret_qds = nullptr;
        delete time_filter;
        return ret;
    }
    std::vector<std::string> lower_case_column_names(columns);
    for (auto& column : lower_case_column_names) {
        to_lowercase_inplace(column);
    }
    std::shared_ptr<ColumnMapping> column_mapping =
        std::make_shared<ColumnMapping>();
    for (size_t i = 0; i < lower_case_column_names.size(); ++i) {
        column_mapping->add(lower_case_column_names[i], static_cast<int>(i),
                            *table_schema);
    }
    std::vector<common::TSDataType> data_types;
    data_types.reserve(lower_case_column_names.size());
    for (size_t i = 0; i < lower_case_column_names.size(); ++i) {
        auto ind = table_schema->find_column_index(lower_case_column_names[i]);
        if (ind < 0) {
            delete time_filter;
            return common::E_COLUMN_NOT_EXIST;
        }
        data_types.push_back(table_schema->get_data_types()[ind]);
    }

    auto device_task_iterator =
        std::unique_ptr<DeviceTaskIterator>(new DeviceTaskIterator(
            lower_case_column_names, table_root, column_mapping,
            meta_data_querier_, tag_filter, table_schema));

    std::unique_ptr<TsBlockReader> tsblock_reader;
    switch (table_query_ordering_) {
        case TableQueryOrdering::DEVICE:
            tsblock_reader = std::unique_ptr<DeviceOrderedTsBlockReader>(
                new DeviceOrderedTsBlockReader(std::move(device_task_iterator),
                                               meta_data_querier_, block_size_,
                                               tsfile_io_reader_, time_filter,
                                               field_filter, offset, limit));
            break;
        case TableQueryOrdering::TIME:
        default:
            delete time_filter;
            ret_qds = nullptr;
            return common::E_UNSUPPORTED_ORDER;
    }
    assert(tsblock_reader != nullptr);
    ret_qds =
        new TableResultSet(std::move(tsblock_reader), lower_case_column_names,
                           data_types, return_mode_);
    return ret;
}

int TableQueryExecutor::query_on_tree(
    const std::vector<std::shared_ptr<IDeviceID>>& devices,
    const std::vector<std::string>& tag_columns,
    const std::vector<std::string>& field_columns, Filter* time_filter,
    ResultSet*& ret_qds) {
    common::PageArena pa;
    pa.init(512, common::MOD_TSFILE_READER);
    int ret = common::E_OK;
    TsFileMeta* file_meta = tsfile_io_reader_->get_tsfile_meta();
    std::unordered_set<MetaIndexNode*> table_inodes;
    for (auto const& device : devices) {
        MetaIndexNode* table_inode;
        if (RET_FAIL(file_meta->get_table_metaindex_node(
                device->get_table_name(), table_inode))) {
        };
        table_inodes.insert(table_inode);
    }

    std::vector<common::ColumnSchema> col_schema;
    for (auto const& tag : tag_columns) {
        col_schema.emplace_back(tag, common::TSDataType::STRING,
                                common::ColumnCategory::TAG);
    }

    std::unordered_map<std::string, common::TSDataType> column_types_map;

    for (auto const& device : devices) {
        bool all_collected = true;
        for (const auto& field_col : field_columns) {
            if (column_types_map.find(field_col) == column_types_map.end()) {
                all_collected = false;
                break;
            }
        }
        if (all_collected) {
            break;
        }

        std::unordered_set<std::string> measurements(field_columns.begin(),
                                                     field_columns.end());
        std::vector<ITimeseriesIndex*> index(measurements.size());
        if (RET_FAIL(tsfile_io_reader_->get_timeseries_indexes(
                device, measurements, index, pa))) {
            return ret;
        }

        for (auto* ts_index : index) {
            if (ts_index != nullptr) {
                std::string measurement_name =
                    ts_index->get_measurement_name().to_std_string();
                if (column_types_map.find(measurement_name) ==
                    column_types_map.end()) {
                    common::TSDataType type = ts_index->get_data_type();
                    column_types_map[measurement_name] = type;
                }
            }
        }
    }

    for (const auto& field_col : field_columns) {
        if (column_types_map.find(field_col) != column_types_map.end()) {
            col_schema.emplace_back(field_col, column_types_map[field_col],
                                    common::ColumnCategory::FIELD);
        } else {
            col_schema.emplace_back(field_col,
                                    common::TSDataType::INVALID_DATATYPE,
                                    common::ColumnCategory::FIELD);
        }
    }

    auto schema = std::make_shared<TableSchema>("default", col_schema);
    schema->set_virtual_table();
    std::shared_ptr<ColumnMapping> column_mapping =
        std::make_shared<ColumnMapping>();
    for (size_t i = 0; i < col_schema.size(); ++i) {
        column_mapping->add(col_schema[i].column_name_, i, *schema);
    }
    std::vector<common::TSDataType> datatypes = schema->get_data_types();
    std::vector<MetaIndexNode*> index_nodes(table_inodes.begin(),
                                            table_inodes.end());
    auto device_task_iterator =
        std::unique_ptr<DeviceTaskIterator>(new DeviceTaskIterator(
            schema->get_measurement_names(), index_nodes, column_mapping,
            meta_data_querier_, nullptr, schema));
    std::unique_ptr<TsBlockReader> tsblock_reader;
    switch (table_query_ordering_) {
        case TableQueryOrdering::DEVICE:
            tsblock_reader = std::unique_ptr<DeviceOrderedTsBlockReader>(
                new DeviceOrderedTsBlockReader(
                    std::move(device_task_iterator), meta_data_querier_,
                    block_size_, tsfile_io_reader_, time_filter, nullptr));
            break;
        case TableQueryOrdering::TIME:
        default:
            ret = common::E_UNSUPPORTED_ORDER;
    }
    assert(tsblock_reader != nullptr);
    ret_qds = new TableResultSet(std::move(tsblock_reader),
                                 schema->get_measurement_names(),
                                 schema->get_data_types());
    return ret;
}

void TableQueryExecutor::destroy_query_data_set(ResultSet* qds) { delete qds; }
}  // end namespace storage
