#pragma once
#include <saas/tools/processors_server/abstract/processor.h>
#include <util/system/rwlock.h>

namespace NRTY {
    class TProcessorsStorage {
    private:
        TMap<TString, IProcessor::TPtr> Processors;
        const TPluginConfigs<IProcessorConfig>& Configs;
        TRWMutex Mutex;
        bool Active;
    public:
        TProcessorsStorage(const TPluginConfigs<IProcessorConfig>& configs)
            : Configs(configs)
        {
            Active = false;
        }

        void Start() {
            TWriteGuard wg(Mutex);
            TSet<TString> names = Configs.GetModules();
            CHECK_WITH_LOG(names.size());
            for (auto&& name : names) {
                const IProcessorConfig* config = Configs.Get<IProcessorConfig>(name);
                CHECK_WITH_LOG(config);
                IProcessor* processor = IProcessor::TFactory::Construct(name);
                CHECK_WITH_LOG(processor);
                Processors[config->GetConfigurationName()] = processor;
                processor->Start(config);
            }
            Active = true;
        }

        void Stop() {
            TWriteGuard wg(Mutex);
            Active = false;
            for (auto&& it : Processors) {
                it.second->Stop();
            }
        }

        void Process(IProcessorContext::TPtr context) {
            TReadGuard wg(Mutex);
            CHECK_WITH_LOG(Active);
            auto it = Processors.find(context->GetProcessorName());
            if (it == Processors.end()) {
                context->UserError("incorrect processor name: " + context->GetProcessorName());
            } else {
                it->second->Process(context);
            }
        }
    };
}
