#pragma once

#include "subscription.h"

#include <boost/beast/http/message.hpp>
#include <boost/beast/http/string_body.hpp>
#include <nlohmann/json.hpp>

#include <cstdint>
#include <optional>
#include <string>
#include <string_view>

namespace crow
{

template <typename Adaptor, typename Handler>
class Connection;

struct Response
{
    template <typename Adaptor, typename Handler>
    friend class crow::Connection;
    using response_type =
        boost::beast::http::response<boost::beast::http::string_body>;

    std::optional<response_type> stringResponse;

    nlohmann::json jsonValue;

    // Identifiers for redfish event sources.
    // Used in event subscription sequence only.
    std::vector<ecclesia::EventSourceId> eventSourceIds;

    void addHeader(std::string_view key, std::string_view value)
    {
        stringResponse->set(key, value);
    }

    void addHeader(boost::beast::http::field key, std::string_view value)
    {
        stringResponse->set(key, value);
    }

    Response() : stringResponse(response_type{})
    {}

    Response(Response&& res) noexcept :
        stringResponse(std::move(res.stringResponse)),
        jsonValue(std::move(res.jsonValue)), completed(res.completed)
    {
        // See note in operator= move handler for why this is needed.
        if (!res.completed)
        {
            completeRequestHandler = std::move(res.completeRequestHandler);
            res.completeRequestHandler = nullptr;
        }
        isAliveHelper = res.isAliveHelper;
        res.isAliveHelper = nullptr;
    }

    ~Response() = default;

    Response(const Response&) = delete;

    Response& operator=(const Response& r) = delete;

    Response& operator=(Response&& r) noexcept;

    void result(unsigned v)
    {
        stringResponse->result(v);
    }

    void result(boost::beast::http::status v)
    {
        stringResponse->result(v);
    }

    boost::beast::http::status result() const
    {
        return stringResponse->result();
    }

    unsigned resultInt() const
    {
        return stringResponse->result_int();
    }

    std::string_view reason() const
    {
        return stringResponse->reason();
    }

    bool isCompleted() const noexcept
    {
        return completed;
    }

    std::string& body()
    {
        return stringResponse->body();
    }

    std::string_view getHeaderValue(std::string_view key) const
    {
        return stringResponse->base()[key];
    }

    void keepAlive(bool k)
    {
        stringResponse->keep_alive(k);
    }

    bool keepAlive() const
    {
        return stringResponse->keep_alive();
    }

    void preparePayload()
    {
        stringResponse->prepare_payload();
    }

    void clear();

    void write(std::string_view bodyPart)
    {
        stringResponse->body() += std::string(bodyPart);
    }

    std::string computeEtag() const;

    void end();

    bool isAlive() const
    {
        return isAliveHelper && isAliveHelper();
    }

    void setCompleteRequestHandler(std::function<void(Response&)>&& handler);

    std::function<void(Response&)> releaseCompleteRequestHandler();

    void setIsAliveHelper(std::function<bool()>&& handler)
    {
        isAliveHelper = std::move(handler);
    }

    std::function<bool()> releaseIsAliveHelper()
    {
        std::function<bool()> ret = std::move(isAliveHelper);
        isAliveHelper = nullptr;
        return ret;
    }

    void setHashAndHandleNotModified();

    void setExpectedHash(std::string_view hash)
    {
        expectedHash = hash;
    }

    void startTimetrace(const std::string& block);
    void endTimetrace(const std::string& block);
    void requestStartTime(const std::string& uri);
    void requestEndTime();
    nlohmann::json timetraceToJson();
    void updateTraceInManagedStore();

  private:
    void addTimetrace(const std::string& marker);
    std::optional<std::string> expectedHash;
    bool completed = false;
    std::function<void(Response&)> completeRequestHandler;
    std::map<std::string, int64_t> markers;
    std::function<bool()> isAliveHelper;
};
} // namespace crow
