#pragma once

#ifndef DBS_HOLDER_05159A83_E8AC_48e0_B3D1_C86228B840E4
#define DBS_HOLDER_05159A83_E8AC_48e0_B3D1_C86228B840E4

#include <string>
#include <vector>

#include <util/generic/noncopyable.h>
#include <util/generic/string.h>
#include <util/generic/vector.h>

#include <Poco/Data/MySQL/Connector.h>

#include <wmconsole/legacy/util/mysql_url.h>
#include <wmconsole/legacy/util/session.h>
#include <wmconsole/legacy/util/atomic_primitives.h>

namespace NWebmaster {

//-----------------------------------------------------------------------------------
struct TDatabaseState {
    size_t db_index;
    u_int  count;
    bool operator<(const TDatabaseState &rhs) const {
        return count < rhs.count;
    }
};

//-----------------------------------------------------------------------------------
class TDatabaseHolder : public TNonCopyable {
    friend struct TDatabaseStateLocker;
public:
    static TDatabaseHolder &instance();

    void init(const std::string &user_db, const std::vector<std::string> &host_db);
    void init(const TString &user_db, const TVector<TString> &host_db);

    WMCSession::Ptr session() const;

    size_t getHostDbCount() const;
    size_t getHostDbId(const std::string &hostname) const;

    void get_dbs_states_snapshot(std::vector<TDatabaseState> &res) const;

private:
    TDatabaseHolder() {}
    std::string check_and_get_conn_str(const std::string &db_str);

    void inc_db_state(size_t db_num);
    void dec_db_state(size_t db_num);

    WMCSession::Ptr temp_session;

    std::string user_db_conn_str;
    std::vector<std::string> host_db_conn_str;
    std::vector<threads::counter> db_states;
};

//-----------------------------------------------------------------------------------
struct TDatabaseStateLocker {
    TDatabaseStateLocker(size_t db_num);
    ~TDatabaseStateLocker();
private:
    size_t db_num;
};

} //namespace NWebmaster

#endif
