#include "stats_server.h"

#include <library/cpp/http/server/response.h>
#include <library/cpp/cgiparam/cgiparam.h>
#include <library/cpp/http/misc/parsed_request.h>
#include <library/cpp/json/json_writer.h>

#include <util/stream/null.h>
#include <util/stream/file.h>
#include <util/string/split.h>


TClientRequest* TStatsServer::CreateClient() {
    return new TStatsServerRequestReplier(Configuration_, MetricStorage_);
}


bool TStatsServerRequestReplier::DoReply(const TReplyParams& replyParams) {
    TParsedHttpFull request(replyParams.Input.FirstLine());
    replyParams.Input.ReadAll(Cnull);

    if (request.Method != "GET") {
        replyParams.Output << THttpResponse(HTTP_NOT_IMPLEMENTED);
        return true;
    }

    TServerRequestData requestData(Socket());
    FillRequestData(requestData, request, replyParams);

    if (!Configuration_.Handles.contains(request.Path) || 
        Configuration_.Handles.at(request.Path).Purpose == EHandlePurpose::NEL
    ) {
        replyParams.Input.ReadAll(Cnull);
        replyParams.Output << THttpResponse(HTTP_NOT_FOUND);
        return true;
    }

    const THandleInfo& handle = Configuration_.Handles.at(request.Path);
    EMetricWriteFormat metricWriteFormat = FindMetricWriteFormat(handle, requestData);
   
    replyParams.Output << "HTTP/1.1 200 Ok\r\n";
    switch (metricWriteFormat) {
        case YASM:
        case SOLOMON_JSON:
            replyParams.Output << "Content-Type: text/json\r\n\r\n";
            break;
        case SOLOMON_SPACK:
            replyParams.Output << "Content-Type: application/x-solomon-spack\r\n\r\n";
            break;
    }

    MetricStorage_.WriteMetrics(metricWriteFormat, handle.TenantName, &replyParams.Output);

    return true;
}

EMetricWriteFormat TStatsServerRequestReplier::FindMetricWriteFormat(
    const THandleInfo& handle,
    const TServerRequestData& requestData
) {
    if (handle.Purpose == EHandlePurpose::UNISTAT) {
        return EMetricWriteFormat::YASM;
    } else if (handle.Purpose == EHandlePurpose::SOLOMON) {
        if (requestData.HeaderInOrEmpty("accept") == "application/x-solomon-spack") {
            return EMetricWriteFormat::SOLOMON_SPACK;
        } else {
            return EMetricWriteFormat::SOLOMON_JSON;
        }
    } else {
        // Unreachable
        ythrow yexception();
    }
}
