#pragma once

#include <list>
#include "Input.h"
#include "Output.h"
#include "IProcessor.h"
#include "Registration.h"

namespace mdd {
    class Registration;
    class ProcessorBase 
        : public IProcessor
        {
    private:
        std::weak_ptr<IModule> _parent;
        int _appendix = 0;

        unsigned int module_counter = 0;
        unsigned int input_counter = 0;
        unsigned int output_counter = 0;

    protected:
        json _base_config;
        ProcessorBase(const std::string& base_config);
        const std::string type = "processor";
        std::string key;
        std::vector<std::shared_ptr<Input>>processor_inputs;
        std::vector<std::shared_ptr<Output>> processor_outputs;
        std::vector<std::shared_ptr<IModule>> modules;
        std::vector<std::shared_ptr<Parameter>> inputs;
        std::vector<std::shared_ptr<Parameter>> outputs;

        bool configureChild(const json& config) override;

    public:
        bool configure(const json& config) override;
        const json& getConfiguration() override;

        void setParent(std::shared_ptr<IModule> parent) override;
        std::vector<std::string> getParentID() override;

        std::string getGeneratorKey() override;
        std::string getType() override;
        std::string setAppendix(int appendix) override;
        int getAppendix() override;
        std::string getID() override;

        std::string addModule(std::shared_ptr<IModule> module) override ;
        void removeModule(std::shared_ptr<IModule> module) override;

        json addInput(std::shared_ptr<IInput> input) override;
        json removeInput(std::shared_ptr<IInput> input) override;
        json addOutput(std::shared_ptr<IOutput> output) override;
        json removeOutput(std::shared_ptr<IOutput> output) override;

        std::vector<std::shared_ptr<Parameter>>& getInputParams() override;
        std::vector<std::shared_ptr<Parameter>>& getOutputParams() override;

        size_t getNumInputs() override;
        size_t getNumOutputs() override;
        std::shared_ptr<IInput> getInput(const json& jid) override;
        std::shared_ptr<IInput> getInput(size_t index) override;
        std::shared_ptr<IOutput> getOutput(const json& jid) override;
        std::shared_ptr<IOutput> getOutput(size_t index) override;

        std::vector<std::shared_ptr<IInput>> getOptimizableInputs() override;
        std::vector<std::shared_ptr<IOutput>> getOptimizableOutputs() override;
        
        std::vector<std::shared_ptr<IModule >>& getModules();
        size_t getNumModuls() override;
        std::shared_ptr<IModule> getModule(size_t index) override;
        std::shared_ptr<IModule> getModule(const json& jid) override;

        bool connect(const std::string& output_id, const std::vector<std::string>& input_ids);
        void disconnect() override;
        void load(const json& j) override;
        json dump() override;
        json getIdentifier() override;

        state update() override { return state::UNCHANGED; };
    };
}
//*/