#include "slot_data.h"


#include <saas/util/external/dc.h>
#include <library/cpp/logger/global/global.h>

#include <util/string/cast.h>
#include <util/string/split.h>

namespace NRTYCluster {
    TString TSlotData::GetDC() const {
        CHECK_WITH_LOG(!!ShortHostName && Port);
        if (!DC) {
            DC = TDatacenterUtil::Instance().GetDatacenter(ShortHostName);
        }
        return DC;
    }

    bool TSlotData::SetDC(const TString& value) const {
        CHECK_WITH_LOG(!!ShortHostName && Port);
        DEBUG_LOG << ShortSlotName() << " dc set as " << value << Endl;
        if (value != "" && value != DC_NOT_DEFINED) {
            DC = value;
            return TDatacenterUtil::Instance().SetDatacenter(ShortHostName, value);
        } else {
            return false;
        }
    }

    TString TSlotData::GetRealHost() const {
        CHECK_WITH_LOG(!!ShortHostName && Port);
        if (!RealHost) {
            RealHost = TDatacenterUtil::Instance().GetRealHost(ShortHostName);
        }
        return RealHost;
    }

    bool TSlotData::SetRealHost(const TString& value) const {
        CHECK_WITH_LOG(!!ShortHostName && Port);
        DEBUG_LOG << ShortSlotName() << " real_host set as " << value << Endl;
        return TDatacenterUtil::Instance().SetRealHost(ShortHostName, value);
    }

    TString TSlotData::GetDCAlias(bool skipError, const TString& aliasIfAbsent) const {
        CHECK_WITH_LOG(!!ShortHostName);
        if (!DCAlias && !TDatacenterUtil::Instance().GetDatacenterAlias(GetDC(), DCAlias)) {
            ERROR_LOG << "Cannot get datacenter alias for " << ShortHostName << Endl;
            if (!skipError) {
                ythrow yexception() << "cannot get datacenter alias for " << ShortHostName;
            }
        }
        if ((DCAlias == "" || DCAlias == ALIAS_NOT_DEFINED) && aliasIfAbsent) {
            return to_upper(aliasIfAbsent);
        }
        return DCAlias;
    }

    void TSlotData::Initialize(const TString& host, ui32 port) {
        FullHostName = host;
        Port = port;

        const TString portStr = ":" + ToString(Port);
        FullSlot = FullHostName + portStr;
        ShortHostName = NSlotNameUtil::ShortHost(host);
        ShortSlot = ShortHostName + portStr;
    }

    bool TSlotData::Parse(TStringBuf slotName, TSlotData& result) {
        TStringBuf host;
        TStringBuf portBuf;
        if (!slotName.TrySplit(':', host, portBuf)) {
            return false;
        }
        ui32 port;
        if (!TryFromString(portBuf, port))
            return false;
        result = TSlotData(TString(host), port);
        return true;
    }

    bool TSlotData::ParseAsEndpointSet(TStringBuf slotName, TSlotData& result) {
        // slotName == cluster@eps_name[:...]
        TString host = TString(slotName.Before(':'));
        ui32 port = 80;
        result = TSlotData(host, port);
        TString dc = NSlotNameUtil::DCFromEndpointSet(host);
        if (dc == "")
            return false;
        result.SetDC(dc);
        return true;
    }
}
