#pragma once

#include <yweb/robot/kiwi/tuplelib/lib/object.h>

namespace NPrivate {
    template <class T>
    inline T GetTupleValue(const NKiwi::NTuples::TTuple* tuple) {
        Y_ASSERT(tuple);
        ui64 value = 0;
#define TYPE(X) if (tuple->CheckValue<X>()) {\
            value = tuple->GetValue<X>();\
            if (value > Max<T>()) {\
                ythrow yexception() << "numerical value overflow for " #X;\
            }\
            return static_cast<T>(value);\
        }

        TYPE(T);
        TYPE(ui64);
        TYPE(ui32);
        TYPE(ui16);
        TYPE(ui8);

#undef TYPE

        ythrow yexception() << "unexpected behaviour";
    }

    template <>
    inline bool GetTupleValue(const NKiwi::NTuples::TTuple* tuple) {
        Y_ASSERT(tuple);
        return tuple->GetValue<bool>();
    }

    template <>
    inline TString GetTupleValue(const NKiwi::NTuples::TTuple* tuple) {
        Y_ASSERT(tuple);
        return tuple->GetValue<TString>();
    }

    inline bool CorrectTuple(const NKiwi::NTuples::TTuple* tuple) {
        return tuple && !tuple->IsNull() && !tuple->IsStub();
    }
}

template<class T>
inline T GetTuple(const NKiwi::TKiwiObject& object, const TString& label, T fallback = T()) {
    const NKiwi::NTuples::TTuple* tuple = object.FindByLabel(label.data());
    return ::NPrivate::CorrectTuple(tuple) ? ::NPrivate::GetTupleValue<T>(tuple) : fallback;
}

inline bool HasTuple(const NKiwi::TKiwiObject& object, const TString& label) {
    const NKiwi::NTuples::TTuple* tuple = object.FindByLabel(label.data());
    return ::NPrivate::CorrectTuple(tuple);
}

struct TKiwiObjectAcquireOptions {
    bool MergeTimestamps = true;
    TString TimestampSuffix;
};

NKiwi::TKiwiObject GetKiwiObject(const TString& data, const TKiwiObjectAcquireOptions& options);
