#pragma once
#include <library/cpp/object_factory/object_factory.h>
#include <saas/library/daemon_base/module/module.h>
#include <util/generic/string.h>
#include <library/cpp/http/misc/httpreqdata.h>
#include <library/cpp/http/misc/httpcodes.h>

class TServerRequestData;

namespace NRTY {

    class IProcessorConfig: public IAbstractModuleConfig {
    public:
        virtual TString GetConfigurationName() const = 0;
        typedef NObjectFactory::TObjectFactory<IProcessorConfig, TString> TFactory;
    };

    class IProcessorContext {
    private:
        bool Replied;
        ui32 Code;

    protected:
        TString ContentType;

    public:

        using TPtr = TAtomicSharedPtr<IProcessorContext>;

        IProcessorContext() {
            Replied = false;
            ContentType = "text/html";
        }

        virtual ~IProcessorContext() {
            CHECK_WITH_LOG(Replied);
        }

        virtual TString GetProcessorName() const = 0;
        virtual void DoReply(ui32 code, const TString& message) = 0;

        virtual const TServerRequestData& GetRD() const = 0;

        virtual ui32 GetResponseCode() const {
            CHECK_WITH_LOG(Replied);
            return Code;
        }

        void SetContentType(const TString& contentType) {
            ContentType = contentType;
        }

        void UserError(const TString& message) {
            Reply(HTTP_BAD_REQUEST, message);
        }

        void ServerError(const TString& message) {
            Reply(HTTP_INTERNAL_SERVER_ERROR, message);
        }

        void Success(const TString& message) {
            Reply(HTTP_OK, message);
        }

        void Reply(ui32 code, const TString& message) {
            DoReply(code, message);
            Code = code;
            Replied = true;
        }
    };

    class IProcessor {
    public:
        using TPtr = TAtomicSharedPtr<IProcessor>;
        using TFactory = NObjectFactory::TObjectFactory<IProcessor, TString>;

        virtual ~IProcessor() {}

        virtual void Start(const IProcessorConfig* config) = 0;
        virtual void Stop() = 0;

        virtual void Process(IProcessorContext::TPtr context) = 0;
    };
}
