#include <util/string/cast.h>

#include "session_factory.h"
#include "session.h"
#include "host_db_hash.h"

const int numberOfPartitions = 512;

using namespace NWebmaster;

//static Poco::Logger& logger(Poco::Logger::get("WMCSession"));


///////////////////////////////////////////////////////////////
//
// WMCHostsSession
//
///////////////////////////////////////////////////////////////

WMCHostsSession::WMCHostsSession(const std::string &dbkey, const std::string &url) {
    hostSessions.push_back(SessionProxy(dbkey, url));
}

WMCHostsSession::WMCHostsSession(const std::string &dbkey, const std::vector<std::string> &urlList) {
    for (size_t i = 0; i < urlList.size(); i++) {
        hostSessions.push_back(SessionProxy(dbkey, urlList[i]));
    }
}

Iterator WMCHostsSession::getHostDbIterator(int i) const {
    return Iterator(i, getHostDbCount());
}

Iterator WMCHostsSession::getPartitionIterator(int i) {
    return Iterator(i, numberOfPartitions);
}

Poco::Data::Session &WMCHostsSession::getHostSessionByName(const std::string &hostname) const {
    return getHostSession(getHostDbId(hostname));
}

int WMCHostsSession::getHostDbId(const std::string &hostname) const {
    return getHostDBHash(hostname.c_str()) % getHostDbCount();
}

//
// Overrided by heirs
//

Poco::Data::Session &WMCHostsSession::getHostSession(int id) const {
    if ((id < 0) || (id >= (int) hostSessions.size())) {
        throw std::runtime_error("invalid host database id: " + ToString(id));
    }

    return hostSessions[id];
}

size_t WMCHostsSession::getHostDbCount() const {
    return hostSessions.size();
}

///////////////////////////////////////////////////////////////
//
// WMCSession
//
///////////////////////////////////////////////////////////////

WMCSession::WMCSession(const std::string &dbkey, const std::string &userUrl, const std::vector<std::string> &hostUrlList)
    : WMCHostsSession(dbkey, hostUrlList), userSession(dbkey, userUrl) {
}

Poco::Data::Session &WMCSession::getUserSession() {
    return userSession;
}

//
// Overrides
//

size_t WMCSession::getHostDbCount() const {
    if (WMCHostsSession::getHostDbCount() == 0) {
        return 1;
    }

    return WMCHostsSession::getHostDbCount();
}

Poco::Data::Session &WMCSession::getHostSession(int id) const {
    if (WMCHostsSession::getHostDbCount() == 0) {
        return const_cast<Poco::Data::Session &>(userSession); // do i ever need this?
    }

    return WMCHostsSession::getHostSession(id);
}

///////////////////////////////////////////////////////////////
//
// Iterator
//
///////////////////////////////////////////////////////////////


Iterator::Iterator(int i, int m)
    : start(i), max(m), current(i) {
}

bool Iterator::next() {
    if (current >= start + max) {
        return false;
    }

    current++;
    return true;
}

int Iterator::get() const {
    return current % max;
}

Poco::FastMutex SessionProxy::_mutex;
