#include "ModuleBase.h"
//#include <boost/algorithm/string.hpp>

namespace mdd {
	class ModuleMerge : public ModuleBase {
	private:
		bool configureChild(const json& config) override;

	public:
		ModuleMerge();
		int addModuleInput();
		int removeModuleInput();
		std::string setInputName(const std::string& input_id, const std::string& new_name);
		state update() override;
	};
	ModuleMerge::ModuleMerge()
		:ModuleBase(R"JSON(
        {
		"configure":{
            "inputs":{
				"value":2
			}
		},
        "GUI":{
            "name":{"value":"Merge"},
            "color":{"value":"#940297"}
        }
        })JSON")
	{
		inputs.push_back(std::make_shared<Input>("Value", 0));
		inputs.push_back(std::make_shared<Input>("Value", 1));
		outputs.push_back(std::make_shared<Output>("Value", 0));
		key = "ModuleMerge";
	}

	int ModuleMerge::addModuleInput() {
		std::vector<double> default_val = { 1 };
		inputs.push_back(std::make_shared<Input>("Value", inputs.size()));
		return inputs.size();
	}

	int ModuleMerge::removeModuleInput() {
		inputs.pop_back();
		return inputs.size();
	}

	std::string ModuleMerge::setInputName(const std::string& input_id, const std::string& new_name) {
		for (int id = 0; id < inputs.size(); ++id) {
			if (getInput(id)->getID() == input_id) {
				getInput(id)->setName(new_name);
				return getInput(id)->getID();
			}
		}
		return "";
	}

	bool ModuleMerge::configureChild(const json& config) {
		bool success = false;
		auto jit = config.find("inputs");
		if (jit != config.end())
		{
			json jval = jit.value()["value"];
			if (jval.is_string())
			{
				jval = json::parse(jval.get<std::string>());
			}
			size_t new_length = jval.get<size_t>();
			size_t length = inputs.size();
			if ((int)length - (int)new_length > 0)
			{
				inputs.erase(inputs.end() - (length - new_length), inputs.end());
			}
			else {
				for (size_t j = length; j < new_length; j++)
				{
					inputs.push_back(std::make_shared<Input>("Value", j));
					inputs.back()->setParent(shared_from_this());
				}
			}
			_base_config["configure"]["inputs"]["value"] = jval;
			return true;
		}
		return false;
	}

	state ModuleMerge::update() {
		std::vector<double>  ret;
		for (size_t i = 0; i < inputs.size(); i++)
		{
			for (size_t j = 0; j < getInput(i)->getValue().size(); j++)
			{
				ret.push_back(getInput(i)->getValue()[j]);
			}
		}
		return getOutput(0)->setValue(ret);
	}
}
