#include "convert.h"
#include "processing_tree.h"

#include <balancer/yt/log-tool/proto/schema.pb.h>

#include <util/datetime/base.h>
#include <util/generic/string.h>
#include <util/string/cast.h>
#include <util/string/escape.h>
#include <util/string/split.h>
#include <util/system/types.h>

using TLog = NBalancerYt::NProto::TLog;
using TProcessingTree = NBalancerYt::NProto::TProcessingTree;
using TProdLog = NBalancerYt::NProto::TProdLog;
using THamsterLog = NBalancerYt::NProto::THamsterLog;

namespace NBalancerYt {
    template<typename TInput>
    void ParseLogRow(const TInput& input, TLog* output) {
        TInstant startTime;
        if (TInstant::TryParseIso8601(input.GetStartTime(), startTime)) {
            output->SetStartTime(startTime.MicroSeconds());
        }

        TDuration duration;
        if (TDuration::TryParse(input.GetDuration(), duration)) {
            output->SetDuration(duration.MicroSeconds());
        }

        output->SetReqId("");
        TProcessingTree processingTree;
        if (TryParseProcessingTree(input.GetProcessingTree(), processingTree)) {
            ProcessingTreeForeach(
                processingTree,
                [&output] (const TProcessingTree& module) {
                    if (module.GetModuleName() != "log_headers") {
                        return;
                    }
                    for (const auto& p : module.GetPayload()) {
                        if (p.HasValue() && p.GetValue().StartsWith("<::X-Req-Id")) {
                            output->SetReqId(p.GetValue());
                        }
                    }
                }
            );
            (*output->MutableProcessingTree()) = std::move(processingTree);
        }
    }
}

template<>
void NBalancerYt::ConvertRowTo<THamsterLog, TLog>(const THamsterLog& input, TLog* output) {
    ParseLogRow<THamsterLog>(input, output);
}

template<>
void NBalancerYt::ConvertRowTo<TProdLog, TLog>(const TProdLog& input, TLog* output) {
    ParseLogRow<TProdLog>(input, output);
}
