/*
 * 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 FILE_OPEN_FILE_H
#define FILE_OPEN_FILE_H

#include <map>
#include <vector>

#include "common/container/list.h"
#include "common/mutex/mutex.h"
#include "common/tsfile_common.h"
#include "reader/bloom_filter.h"
#include "utils/storage_utils.h"

namespace storage {

/*
 * Data of a TSStore consist of:
 * - some tsfiles
 * - some immutable tvlists
 * - the active tvlist.
 *
 * When some immutable tvlists are flushed into tsfile, we
 * should guarantee that we have a consisteny view of TSStore
 * data. That means we should see one and only one of the
 * flushed immutable tvlist or the corresponding tsfile.
 * Otherwise, we may see duplicated data in the immutable tvlist
 * and the tsfile, or we may lose the data if we see neither
 * of them.
 * So we should do the following steps atomically:
 * - remove the immutable tvlist from tsstore
 * - make it visible in tsfile_mgr
 */

// opened tsfile
class OpenFile {
   public:
    // maybe use sorted array instead of map.
    typedef std::map<common::TsID, TimeRange> TsTimeRangeMap;
    typedef std::map<common::TsID, TimeRange>::iterator TsTimeRangeMapIterator;

   public:
    OpenFile()
        : file_id_(),
          file_path_(),
          fd_(-1),
          bloom_filter_(nullptr),
          ts_time_range_map_(nullptr),
          mutex_() {}
    int init();
    // reset the map to reclaim memory
    void reset();

    void set_file_id_and_path(const common::FileID &file_id,
                              const std::string &file_path);
    FORCE_INLINE common::FileID get_file_id() { return file_id_; }
    FORCE_INLINE std::string get_file_path() { return file_path_; }
    int build_from(const std::vector<TimeseriesTimeIndexEntry> &time_index_vec);
    int add(const common::TsID &ts_id, const TimeRange &time_range);

    bool contain_timeseries(const common::TsID &ts_id) const;
    int get_time_range(const common::TsID &ts_id,
                       TimeRange &ret_time_range) const;

#ifndef NDEBUG
    friend std::ostream &operator<<(std::ostream &out, OpenFile &open_file) {
        out << "file_id=" << open_file.file_id_
            << ", file_path=" << open_file.file_path_
            << ", fd=" << open_file.fd_ << ", ts_time_range_map=";
        if (open_file.ts_time_range_map_ == nullptr) {
            out << "nil" << std::endl;
        } else {
            TsTimeRangeMapIterator it;
            out << std::endl;
            for (it = open_file.ts_time_range_map_->begin();
                 it != open_file.ts_time_range_map_->end();
                 it++) {  // cppcheck-suppress postfixOperator
                out << "{ts_id=" << it->first.to_string()
                    << ", ts_time_range={start_time=" << it->second.start_time_
                    << ", end_time=" << it->second.end_time_ << "}}";
            }
        }
        return out;
    }
#endif

   private:
    common::FileID file_id_;
    std::string file_path_;
    int fd_;
    /*
     * Why use pointer instead of object:
     * we may want to reclaim the memory in case of memory overused.
     */
    BloomFilter *bloom_filter_;
    TsTimeRangeMap
        *ts_time_range_map_;  // TODO: use custom hashtable to monitor memory.
    mutable common::Mutex mutex_;
};

class OpenFileFactory {
   public:
    static OpenFile *alloc() {
        void *buf =
            common::mem_alloc(sizeof(OpenFile), common::MOD_OPEN_FILE_OBJ);
        if (IS_NULL(buf)) {
            return nullptr;
        }
        return new (buf) OpenFile;
    }

    static void free(OpenFile *of) {
        if (of != nullptr) {
            common::mem_free(of);
        }
    }
};

}  // end namespace storage
#endif  // FILE_OPEN_FILE_H
