#pragma once

#include "sqlite_variant.h"

#include <boost/noncopyable.hpp>

#include <sqlite3.h>

#include <memory>

namespace maps {
namespace mrc {
namespace common {

class SQLiteDb : private boost::noncopyable {
public:
    explicit SQLiteDb(const std::string& path,
                      int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE
                                  | SQLITE_OPEN_NOMUTEX);
    void exec(const std::string& sql,
              const std::vector<SQLiteVariant>& params = {});
    bool fetch(std::vector<SQLiteVariant>& row);
    int changes() { return sqlite3_changes(db_.get()); }

private:
    struct DbDeleter {
        void operator()(sqlite3* db) const { sqlite3_close_v2(db); }
    };

    struct StmtDeleter {
        void operator()(sqlite3_stmt* stmt) const { sqlite3_finalize(stmt); }
    };

    std::unique_ptr<sqlite3, DbDeleter> db_;
    std::unique_ptr<sqlite3_stmt, StmtDeleter> stmt_;

    std::string errmsg() const;
    void check(int result) const;
    void step();
    int bind(size_t order, const SQLiteVariant& param);
};

} // common
} // mrc
} // maps
