/*
 * 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.
 */

#ifndef READER_SCAN_ITERATOR_H
#define READER_SCAN_ITERATOR_H

#include <stdint.h>

#include "common/container/list.h"
#include "common/seq_tvlist.h"
#include "common/tsblock/tsblock.h"
#include "file/open_file.h"
#include "file/tsfile_io_reader.h"
#include "utils/db_utils.h"
#include "utils/storage_utils.h"

namespace storage {

enum DataRunType {
    DRT_TVLIST = 0,
    DRT_TSFILE = 1,
    DRT_INVALID = 2,
};

/*
 * All KV range are sorted within one DataRun.
 * KV ranges in different runs may overlap with each other.
 *
 * One or more SeqTVLists are a DataRun,
 * One or more TsFileReader are a DataRun.
 */
class DataRun {
   public:
    DataRun(DataRunType run_type, common::ColumnSchema* col_schema,
            common::PageArena* pa)
        : run_type_(run_type),
          col_schema_(col_schema),
          time_range_(),
          tvlist_list_(pa),
          tvlist_list_iter_(),
          tsfile_list_(pa),
          tsfile_list_iter_(),
          io_reader_(),
          ssi_(nullptr),
          tuple_desc_() {}

    int get_next(common::TsBlock* ret_block, TimeRange& ret_time_range,
                 bool alloc);

    const char* get_data_run_type_name(DataRunType type) {
        ASSERT(type == DRT_TVLIST || type == DRT_TSFILE);
        static const char* names[2] = {"TVLIST", "TSFILE"};
        return names[type];
    }
    int remove_tsfile(const common::FileID& file_id);

#ifndef NDEBUG
    friend std::ostream& operator<<(std::ostream& out, DataRun& data_run) {
        out << "type=" << data_run.get_data_run_type_name(data_run.run_type_)
            << ", time_range={start=" << data_run.time_range_.start_time_
            << ", end=" << data_run.time_range_.end_time_ << "}";
        if (DRT_TVLIST == data_run.run_type_) {
            common::SimpleList<SeqTVListBase*>::Iterator it;
            int count = 0;
            out << ", tvlist_list={";
            for (it = data_run.tvlist_list_.begin();
                 it != data_run.tvlist_list_.end(); it++) {
                if (it == data_run.tvlist_list_.begin()) {
                    out << "[" << count << "]" << (void*)it.get();
                } else {
                    out << ", [" << count << "]" << (void*)it.get();
                }
                count++;
            }
            out << "}";
        } else if (DRT_TSFILE == data_run.run_type_) {
            common::SimpleList<OpenFile*>::Iterator it;
            int count = 0;
            out << ", tsfile_list={";
            for (it = data_run.tsfile_list_.begin();
                 it != data_run.tsfile_list_.end(); it++) {
                if (it == data_run.tsfile_list_.begin()) {
                    out << "[" << count << "]" << *it.get();
                } else {
                    out << ", [" << count << "]" << *it.get();
                }
                count++;
            }
            out << "}";
        }
        return out;
    }
#endif

   private:
    int tvlist_get_next(common::TsBlock* ret_block, TimeRange& ret_time_range,
                        bool alloc);
    int fill_tsblock_from_tvlist(SeqTVListBase* tvlist,
                                 common::TsBlock* ret_block,
                                 TimeRange& ret_time_range);
    template <typename T>
    int fill_tsblock_from_typed_tvlist(SeqTVListBase* tvlist,
                                       common::TsBlock* ret_block,
                                       TimeRange& ret_time_range);
    int tsfile_get_next(common::TsBlock* ret_block, TimeRange& ret_time_range,
                        bool alloc);
    int reinit_io_reader(common::SimpleList<OpenFile*>::Iterator& it,
                         common::PageArena* pa = nullptr);
    common::TsBlock* alloc_tsblock();

   public:
    DataRunType run_type_;
    common::ColumnSchema* col_schema_;
    TimeRange time_range_;

    // invalid if run_type_ is DRT_TSFILE
    common::SimpleList<SeqTVListBase*> tvlist_list_;
    common::SimpleList<SeqTVListBase*>::Iterator tvlist_list_iter_;

    // invalid if run_type_ is DRT_TVLIST
    common::SimpleList<OpenFile*> tsfile_list_;
    common::SimpleList<OpenFile*>::Iterator tsfile_list_iter_;
    // TODO may bind TsFileIOReader on OpenFile ?
    TsFileIOReader io_reader_;
    TsFileSeriesScanIterator* ssi_;
    common::TupleDesc tuple_desc_;
};

class DataScanIterator {
   public:
    DataScanIterator()
        : col_schema_(),
          page_arena_(),
          data_run_list_(&page_arena_),
          cursor_() {}
    ~DataScanIterator() {}
    int init() { return common::E_OK; }
    void destory() {
        close();
        page_arena_.destroy();
    }
    void close() {
        // TODO
    }

    DataRun* alloc_data_run(DataRunType run_type);
    FORCE_INLINE int add_data_run(DataRun* data_run) {
        ASSERT(data_run != nullptr);
        return data_run_list_.push_back(data_run);
    }
    void reset_for_retry() { page_arena_.reset(); }

    /*
     * get next tsblock
     * return value
     *        E_OK  -  succ
     *        E_INVALID_ARG - ret_block not init
     *        E_NO_MORE_DATA - reader over
     */
    int get_next(common::TsBlock* block, bool alloc_tsblock = false);
    void set_col_schema(const common::ColumnSchema& col_schema) {
        col_schema_ = col_schema;
    }

#ifndef NDEBUG
    void DEBUG_dump_data_run_list();
#endif

   private:
    common::ColumnSchema col_schema_;
    common::PageArena page_arena_;
    common::SimpleList<DataRun*> data_run_list_;
    common::SimpleList<DataRun*>::Iterator cursor_;
};

}  // end namespace storage
#endif  // READER_SCAN_ITERATOR_H
