#include "dc.h"

#include <util/string/vector.h>

using namespace NSlotNameUtil;

namespace NSlotNameUtil {
    inline TString PrettyHost(const TString& host) {
        TVector<TString> parts;
        StringSplitter(host).Split('.').ParseInto(&parts);
        if (parts.size() <= 2) {
            return host;
        } else if (host.find(".yp") != TString::npos) {
            return parts[0] + "." + parts[1];
        } else {
            return parts[0];
        }
    }
}

bool TDatacenterUtil::SetDatacenter(const TString& host, const TString& value) {
    const TString hostShort = ShortHost(host);
    {
        TReadGuard rg(Mutex);
        if (DCByHost.contains(hostShort)) {
            return false;
        }
    }
    TWriteGuard wg(Mutex);
    if (DCByHost.contains(hostShort)) {
        return false;
    }
    DCByHost[hostShort] = value;
    return true;
}


TString TDatacenterUtil::GetDatacenter(const TString& host) {
    const TString hostShort = ShortHost(host);

    if (ApiHost == "local") {
        TVector<TString> s = SplitString(hostShort, "__");
        if (s.size() < 2) {
            return "local";
        } else {
            return s.front();
        }
    } else {
        TReadGuard rg(Mutex);
        auto i = DCByHost.find(hostShort);
        if (i != DCByHost.end()) {
            return i->second;
        } else {
            return DC_NOT_DEFINED;
        }
    }
}

//todo: code duplication

bool TDatacenterUtil::SetRealHost(const TString& host, const TString& value) {
    const TString hostShort = ShortHost(host);
    {
        TReadGuard rg(Mutex);
        if (RealHostByContainer.contains(hostShort)) {
            return false;
        }
    }
    TWriteGuard wg(Mutex);
    if (RealHostByContainer.contains(hostShort)) {
        return false;
    }
    RealHostByContainer[hostShort] = value;
    return true;
}

TString TDatacenterUtil::GetRealHost(const TString& host) {
    const TString hostShort = ShortHost(host);

    if (ApiHost == "local") {
        TVector<TString> s = SplitString(hostShort, "__");
        if (s.size() < 2) {
            return "local";
        } else {
            return s.front();
        }
    } else {
        TReadGuard rg(Mutex);
        auto i = RealHostByContainer.find(hostShort);
        if (i != RealHostByContainer.end()) {
            return i->second;
        } else {
            return HOST_NOT_DEFINED;
        }
    }
}

bool TDatacenterUtil::SetPodIP(const TString& fqdn, const TString& ip) {
    TWriteGuard wg(Mutex);
    IPByPod[fqdn] = ip;
    return true;
}

TString TDatacenterUtil::GetPodIP(const TString& fqdn) {
    TReadGuard rg(Mutex);
    auto i = IPByPod.find(fqdn);
    if (i != IPByPod.end()) {
        return i->second;
    } else {
        return "";
    }
}

bool TDatacenterUtil::AddDatacenterAlias(const TString& dc, const TString& alias) {
    std::pair<TDatacenterAliases::iterator, bool> insertionResult = AliasByFullNameMap.insert(TDatacenterAliases::value_type(dc, alias));
    return insertionResult.second;
}

bool TDatacenterUtil::GetDatacenterAlias(const TString& dc, TString& result) {
    auto a = AliasByFullNameMap.find(dc);
    if (a == AliasByFullNameMap.end()) {
        return false;
    }

    result = a->second;
    return true;
}

TString TDatacenterUtil::GetDatacenterAlias(const TString& dc) {
    TString result;
    if (!GetDatacenterAlias(dc, result)) {
        ythrow yexception() << "cannot get alias for datacenter " << dc;
    }
    return result;
}

TDatacenterUtil& TDatacenterUtil::Instance() {
    return *Singleton<TDatacenterUtil>();
}
