#pragma once

#ifndef LAZY_PROXY_DAT_FILE_H_C171C91DB6AB42a783B46494DD37B6BD
#define LAZY_PROXY_DAT_FILE_H_C171C91DB6AB42a783B46494DD37B6BD

#include <util/generic/noncopyable.h>

namespace NWebmaster {
namespace dat_files {

template <typename t_dat_file_type>
class lazy_dat_file_proxy : public TNonCopyable {
public:
    typedef t_dat_file_type value_type;

    lazy_dat_file_proxy(const std::string &file_name, const std::string &path);

    template <typename t_p1, typename t_p2, typename t_p3>
    lazy_dat_file_proxy(const std::string &file_name, const std::string &path, const t_p1 &p1, const t_p2 &p2, const t_p3 &p3);

    ~lazy_dat_file_proxy();

    inline bool is_open();
    inline void reinit();
    inline void check_reinit();
    void close();
    inline value_type &operator()();

private:
    value_type f;
    const std::string file_name;
    const std::string &path;
    struct stat st;
};

template <typename t_dat_file_type>
lazy_dat_file_proxy<t_dat_file_type>::lazy_dat_file_proxy(const std::string &file_name, const std::string &path) :
    f(), file_name(file_name), path(path) {
}

template <typename t_dat_file_type>
template <typename t_p1, typename t_p2, typename t_p3>
lazy_dat_file_proxy<t_dat_file_type>::lazy_dat_file_proxy(const std::string &file_name, const std::string &path, const t_p1 &p1, const t_p2 &p2, const t_p3 &p3) :
    f(p1, p2, p3), file_name(file_name), path(path) {
}

template <typename t_dat_file_type>
lazy_dat_file_proxy<t_dat_file_type>::~lazy_dat_file_proxy() {
    close();
}

template <typename t_dat_file_type>
bool lazy_dat_file_proxy<t_dat_file_type>::is_open() {
    if (!f.IsOpen()) {
        safe_dat_open(f, path + file_name, st);
    }
    return f.IsOpen();
}

template <typename t_dat_file_type>
void lazy_dat_file_proxy<t_dat_file_type>::reinit() {
    close();
}

template <typename t_dat_file_type>
void lazy_dat_file_proxy<t_dat_file_type>::check_reinit() {
    safe_check_reinit(*this, path + file_name, st);
}

template <typename t_dat_file_type>
void lazy_dat_file_proxy<t_dat_file_type>::close() {
    if (f.IsOpen()) {
        safe_dat_close(f);
    }
}

template <typename t_dat_file_type>
typename lazy_dat_file_proxy<t_dat_file_type>::value_type &lazy_dat_file_proxy<t_dat_file_type>::operator()() {
    if (!f.IsOpen()) {
        safe_dat_open(f, path + file_name, st);
    }
    return f;
}

} //dat_files
} //namespace NWebmaster

#endif //LAZY_PROXY_DAT_FILE_H_C171C91DB6AB42a783B46494DD37B6BD
