#pragma once

#include "frames.h"
#include "response_stream.h"

#include <balancer/client/experimental/error/error.h>

#include <infra/libs/outcome/result.h>

#include <util/datetime/base.h>

#include <functional>

namespace NHttp {
/// Интерфейс IResponseParser реализует логику проверки и десериализации входящих данных
class IResponseParser {
  public:
    using TResult = TExpected<std::any, TError>;
    using THandler = std::function<void (TResult)>;

    virtual ~IResponseParser() = default;

    /// Метод Parse реализует логику проверки и десериализации входящих данных.
    /// Если при десериализации могут быть прочитаны данные, относящиеся к следующему фрейму,
    /// то рекомендуется использовать флаг peek у метода IResponseStream::Read.
    /// С их помощью можно получить данные из стрима, но при этом они будут доступны для повторного чтения.
    /// \param stream поток входящих данных
    /// \param deadline максимальное время ожидания ответа
    /// \param callback должен быть вызван после проверки и десериализации данных
    virtual void Parse(IResponseStream& stream, TInstant deadline, THandler callback) noexcept = 0;
};

/// Концепт CResponseParser проверяет, что класс наследуется от IResponseParser
/// и в нём указан десериализуемый тип.
template<typename T>
concept CResponseParser =
    std::is_base_of_v<IResponseParser, T> &&
    requires {
        typename T::TParsedType;
    };
}

