#include "hostid_partition_util.h"

#include <Poco/String.h>

//////////////////////////////////////////////
//
// HostIdPartitionUtil
//
///////////////////////////////////////////////

std::map<std::string, int> HostIdPartitionUtil::partitions;

HostIdPartitionUtil *HostIdPartitionUtil::instance() {
    static HostIdPartitionUtil sfInstance;
    return &sfInstance;
}

void HostIdPartitionUtil::replaceName(std::string &sql, const std::string &name, int n) {
    std::string s(Poco::toLower(sql));
    std::ostringstream os;
    os << std::setw(3) << std::setfill('0') << n;
    std::string numStr = os.str();
    std::string::size_type len = name.length();
    std::string::size_type beginPos = s.rfind(name);
    while (beginPos != std::string::npos) {
        std::string::size_type endPos = beginPos + len;

        if ((beginPos == 0 || !isNameChar(s[beginPos - 1]))
                && (endPos == std::string::npos || !isNameChar(s[endPos]))) {
            sql.insert(endPos, numStr);
        }

        if (beginPos == 0) {
            break;
        }
        beginPos = s.rfind(name, beginPos - 1);
    }
}

std::string HostIdPartitionUtil::partitionedSQL(const std::string &sql, long long hostId) {
    if (sql.length() == 0) {
        return sql;
    }

    std::string s(sql);

    for (std::map<std::string, int>::const_iterator i = partitions.begin(); i != partitions.end(); ++i) {
        int numOfParts = i->second;
        int partitionNum = getPartition(hostId, numOfParts);
        replaceName(s, i->first, partitionNum);
    }

    return s;
}

/////////////////////////////////////////////////////////
//
// HostIdPartitionUtil::Iterator
//
/////////////////////////////////////////////////////////

HostIdPartitionUtil::Iterator::Iterator(long from) {
    fStartFrom = from % 512;
    fCurrent = from % 512;
}

/*HostIdPartitionUtil::Iterator::Iterator(long item, long total)
{
    item = item % total;
    fStartFrom = item * (512 / total);
    fCurrent = item * (512 / total);
}*/

bool HostIdPartitionUtil::Iterator::next() {
    if ((fCurrent + 1) % 512 == fStartFrom) {
        return false;
    }

    fCurrent++;
    fCurrent = fCurrent % 512;
    return true;
}

std::string HostIdPartitionUtil::Iterator::partitionedSQL(const std::string &sql) {
    return HostIdPartitionUtil::instance()->partitionedSQL(sql, fCurrent);
}
