
#include "Manual.hpp"

#define OUTPUT_SCALE "output_scale"

void Manual::reset() {
	_trigger.reset();
	_pulse.process(10.0f);
}

void Manual::sampleRateChange() {
	_sampleTime = APP->engine->getSampleTime();
}

json_t* Manual::saveToJson(json_t* root) {
	root = TriggerOnLoadModule::saveToJson(root);
	json_object_set_new(root, OUTPUT_SCALE, json_real(_outputScale));
	return root;
}

void Manual::loadFromJson(json_t* root) {
	TriggerOnLoadModule::loadFromJson(root);
	json_t* os = json_object_get(root, OUTPUT_SCALE);
	if (os) {
		_outputScale = json_real_value(os);
	}
}

void Manual::processAll(const ProcessArgs& args) {
	bool initialPulse = false;
	if (_initialDelay && !_initialDelay->next()) {
		initialPulse = true;
		delete _initialDelay;
		_initialDelay = NULL;
	}

	bool high = _trigger.process(params[TRIGGER_PARAM].getValue()) || _trigger.isHigh() || (initialPulse && _triggerOnLoad && _shouldTriggerOnLoad);
	if (high) {
		_pulse.trigger(0.001f);
	}
	high = _pulse.process(_sampleTime);

	float out = high ? (5.0f * _outputScale) : 0.0f;
	outputs[OUT1_OUTPUT].setVoltage(out);
	outputs[OUT2_OUTPUT].setVoltage(out);
	outputs[OUT3_OUTPUT].setVoltage(out);
	outputs[OUT4_OUTPUT].setVoltage(out);
	outputs[OUT5_OUTPUT].setVoltage(out);
	outputs[OUT6_OUTPUT].setVoltage(out);
	outputs[OUT7_OUTPUT].setVoltage(out);
	outputs[OUT8_OUTPUT].setVoltage(out);
}

struct ManualWidget : TriggerOnLoadModuleWidget {
	static constexpr int hp = 3;

	ManualWidget(Manual* module)
	: TriggerOnLoadModuleWidget("Trigger on load")
	{
		setModule(module);
		box.size = Vec(RACK_GRID_WIDTH * hp, RACK_GRID_HEIGHT);
		setPanel(box.size, "Manual");
		createScrews();

		// generated by svg_widgets.rb
		auto triggerParamPosition = Vec(13.5, 22.0);

		auto out1OutputPosition = Vec(10.5, 57.0);
		auto out2OutputPosition = Vec(10.5, 87.0);
		auto out3OutputPosition = Vec(10.5, 117.0);
		auto out4OutputPosition = Vec(10.5, 147.0);
		auto out5OutputPosition = Vec(10.5, 177.0);
		auto out6OutputPosition = Vec(10.5, 207.0);
		auto out7OutputPosition = Vec(10.5, 237.0);
		auto out8OutputPosition = Vec(10.5, 267.0);
		// end generated by svg_widgets.rb

		addParam(createParam<Button18>(triggerParamPosition, module, Manual::TRIGGER_PARAM));

		addOutput(createOutput<Port24>(out1OutputPosition, module, Manual::OUT1_OUTPUT));
		addOutput(createOutput<Port24>(out2OutputPosition, module, Manual::OUT2_OUTPUT));
		addOutput(createOutput<Port24>(out3OutputPosition, module, Manual::OUT3_OUTPUT));
		addOutput(createOutput<Port24>(out4OutputPosition, module, Manual::OUT4_OUTPUT));
		addOutput(createOutput<Port24>(out5OutputPosition, module, Manual::OUT5_OUTPUT));
		addOutput(createOutput<Port24>(out6OutputPosition, module, Manual::OUT6_OUTPUT));
		addOutput(createOutput<Port24>(out7OutputPosition, module, Manual::OUT7_OUTPUT));
		addOutput(createOutput<Port24>(out8OutputPosition, module, Manual::OUT8_OUTPUT));
	}

	void contextMenu(Menu* menu) override {
		TriggerOnLoadModuleWidget::contextMenu(menu);

		auto m = dynamic_cast<Manual*>(module);
		assert(m);

		OptionsMenuItem* o = new OptionsMenuItem("Output");
		o->addItem(OptionMenuItem("+5V", [m]() { return m->_outputScale == 1.0f; }, [m]() { m->_outputScale = 1.0f; }));
		o->addItem(OptionMenuItem("+10V", [m]() { return m->_outputScale == 2.0f; }, [m]() { m->_outputScale = 2.0f; }));
		OptionsMenuItem::addToMenu(o, menu);
	}
};

Model* modelManual = bogaudio::createModel<Manual, ManualWidget>("Bogaudio-Manual", "MANUAL", "Button controlled gates / triggers", "Controller");
