#pragma once

#include <library/cpp/json/writer/json_value.h>
#include <util/datetime/base.h>
#include <util/generic/string.h>

namespace NUtil {

    class THttpReply {
    private:
        bool IsConnected_;
        bool IsCorrectReply_;
        ui32 Code_;
        TString ErrorMessage_;
        TString Content_;
    public:

        THttpReply() {
            IsConnected_ = false;
            IsCorrectReply_ = false;
            Code_ = 0;
        }

        NJson::TJsonValue Serialize() const;
        void Deserialize(const NJson::TJsonValue& value);

        bool IsSuccessReply() const {
            return Code_ == 200 || Code_ == 202;
        }

        bool IsUserError() const {
            return Code_ >= 400 && Code_ < 500;
        }

        bool IsServerError() const {
            return Code_ >= 500;
        }

        void SetIsConnected(bool value) {
            IsConnected_ = value;
        }

        void SetIsCorrectReply(bool value) {
            IsCorrectReply_ = value;
        }

        bool IsCorrectReply() {
            return IsCorrectReply_;
        }

        ui32 Code() const {
            return Code_;
        }

        void SetCode(ui32 value) {
            Code_ = value;
        }

        const TString& Content() const {
            return Content_;
        }

        void SetContent(const TString& value) {
            Content_ = value;
        }

        void SetErrorMessage(const TString& value) {
            ErrorMessage_ = value;
        }

        const TString& ErrorMessage() const {
            return ErrorMessage_;
        }
    };

    class THttpRequest {
    private:
        TString Command;
        TString PostData;
        bool IsHttps = false;
        TDuration Timeout = TDuration::MilliSeconds(100);
        ui32 SendAttemptionsMax = 5;
        bool RetryOn5xx = false;
        TDuration SleepingPause = TDuration::MilliSeconds(100);
        THashMap<TString, TString> AdditionHeaders;
    public:

        THttpRequest(const TString& command)
            : Command(command)
        {}

        THttpRequest(const TString& command, const TString& postData)
            : Command(command)
            , PostData(postData)
        {}

        THttpRequest& SetHeader(const TString& header, const TString& value) {
            AdditionHeaders[header] = value;
            return *this;
        }

        THttpRequest& SetIsHttps(bool value = true) {
            IsHttps = value;
            return *this;
        }

        THttpRequest& SetCommand(const TString& value) {
            Command = value;
            return *this;
        }

        THttpRequest& SetPostData(const TString& value) {
            PostData = value;
            return *this;
        }

        THttpRequest& SetSleepingPause(ui32 pauseMs) {
            SleepingPause = TDuration::MilliSeconds(pauseMs);
            return *this;
        }

        THttpRequest& SetTimeout(ui32 timeoutMs) {
            Timeout = TDuration::MilliSeconds(timeoutMs);
            return *this;
        }

        THttpRequest& SetAttemptionsMax(ui32 sendAttemptionsMax) {
            SendAttemptionsMax = sendAttemptionsMax;
            return *this;
        }

        THttpRequest& SetRetryOn5xx(bool retryOn5xx) {
            RetryOn5xx = retryOn5xx;
            return *this;
        }

        THttpReply Execute(const TString& host, ui32 port);
    };

}
