#pragma once
#include <DataStreams/IProfilingBlockInputStream.h>
#include <Storages/MergeTree/MergeTreeThreadSelectBlockInputStream.h>
#include <Storages/MergeTree/MergeTreeData.h>
#include <Storages/MergeTree/MarkRange.h>
#include <Storages/MergeTree/MergeTreeBlockReadUtils.h>
#include <Storages/SelectQueryInfo.h>

namespace DB
{


/// Used to read data from single part with select query
/// Cares about PREWHERE, virtual columns, indexes etc.
/// To read data from multiple parts, Storage (MergeTree) creates multiple such objects.
class MergeTreeSelectBlockInputStream : public MergeTreeBaseSelectBlockInputStream
{
public:
    MergeTreeSelectBlockInputStream(
        const MergeTreeData & storage,
        const MergeTreeData::DataPartPtr & owned_data_part,
        size_t max_block_size_rows,
        size_t preferred_block_size_bytes,
        size_t preferred_max_column_in_block_size_bytes,
        Names column_names,
        const MarkRanges & mark_ranges,
        bool use_uncompressed_cache,
        const PrewhereInfoPtr & prewhere_info,
        bool check_columns,
        size_t min_bytes_to_use_direct_io,
        size_t max_read_buffer_size,
        bool save_marks_in_cache,
        const Names & virt_column_names = {},
        size_t part_index_in_query = 0,
        bool quiet = false);

    ~MergeTreeSelectBlockInputStream() override;

    String getName() const override { return "MergeTree"; }

    Block getHeader() const override;

    /// Closes readers and unlock part locks
    void finish();

protected:

    bool getNewTask() override;

private:
    Block header;

    /// Used by Task
    Names required_columns;
    /// Names from header. Used in order to order columns in read blocks.
    Names ordered_names;
    NameSet column_name_set;
    NamesAndTypesList columns;
    NamesAndTypesList pre_columns;

    /// Data part will not be removed if the pointer owns it
    MergeTreeData::DataPartPtr data_part;
    /// Forbids to change columns list of the part during reading
    std::shared_lock<std::shared_mutex> part_columns_lock;

    /// Mark ranges we should read (in ascending order)
    MarkRanges all_mark_ranges;
    /// Total number of marks we should read
    size_t total_marks_count = 0;
    /// Value of _part_index virtual column (used only in SelectExecutor)
    size_t part_index_in_query = 0;

    bool check_columns;
    String path;
    bool is_first_task = true;

    Logger * log = &Logger::get("MergeTreeSelectBlockInputStream");
};

}
