#ifndef BRICK_EMITS_H
#define BRICK_EMITS_H

#include "brick_base.h"
#include "brick_manager.h"


class BrickEmitBase: public BrickBase {
public: BrickEmitBase(int inputs_num = 1, int outputs_num = 1, int parameters_num = 0): BrickBase(inputs_num, outputs_num, parameters_num) {lib = "Emitters";}
};


class BrickEmitConst: public BrickEmitBase {
	MBRICK(BrickEmitConst)
	BrickEmitConst(double value = 1.): BrickEmitBase(0, 1, 1) {parameters[0].setValue(value); type = "Const"; setName(type); paramNames[0] = "Const";}
	void setValue(double value) {parameters[0].setValue(value);}
	virtual bool tick_body(double time) {outputs[0] = parameters[0].toFloat(); return true;}
};
ADD_NEW_TO_COLLECTION(Emitters, BrickEmitConst)


class BrickEmitLinear: public BrickEmitBase {
	MBRICK(BrickEmitLinear)
	BrickEmitLinear(double start_value = 0., double slope = 1.): BrickEmitBase(2, 1) {setParameters(start_value, slope); type = "Linear"; setName(type); inNames[0] = "Start"; inNames[1] = "Slope";}
	enum Inputs {StartValue, Slope};
	void setParameters(double start_value, double slope) {inputs[StartValue] = start_value; inputs[Slope] = slope;}
	virtual bool tick_body(double time);
};
ADD_NEW_TO_COLLECTION(Emitters, BrickEmitLinear)


class BrickEmitSin: public BrickEmitBase {
	MBRICK(BrickEmitSin)
	BrickEmitSin(double amplitude = 1., double frequency = 1., double phase_shift = 0.): BrickEmitBase(3, 1) {setParameters(amplitude, frequency, phase_shift); type = "Sin"; setName(type); inNames[0] = "Amplitude"; inNames[1] = "Frequency, Hz"; inNames[2] = "Phase Shift, rad";}
	enum Inputs {Amplitude, Frequency, PhaseShift};
	void setParameters(double amplitude, double frequency, double phase_shift) {inputs[Amplitude] = amplitude; inputs[Frequency] = frequency; inputs[PhaseShift] = phase_shift;}
	virtual bool tick_body(double time);
};
ADD_NEW_TO_COLLECTION(Emitters, BrickEmitSin)


class BrickEmitDelta: public BrickEmitBase {
	MBRICK(BrickEmitDelta)
	BrickEmitDelta(double time = 0.): BrickEmitBase(1, 1) {setTime(time); type = "Delta"; setName(type); inNames[0] = "Time, s";}
	enum Inputs {Time};
	void setTime(double time) {inputs[Time] = time;}
	virtual bool tick_body(double time);
};
ADD_NEW_TO_COLLECTION(Emitters, BrickEmitDelta)


class BrickEmitStep: public BrickEmitBase {
	MBRICK(BrickEmitStep)
	BrickEmitStep(double time = 0., double start = 0., double finish = 1.): BrickEmitBase(3, 1) {setParameters(time, start, finish); type = "Step"; setName(type); inNames[0] = "Time, s"; inNames[1] = "Start Value"; inNames[2] = "Finish Value";}
	enum Inputs {Time, StartValue, FinishValue};
	void setParameters(double time, double start, double finish) {inputs[Time] = time; inputs[StartValue] = start; inputs[FinishValue] = finish;}
	virtual bool tick_body(double time);
};
ADD_NEW_TO_COLLECTION(Emitters, BrickEmitStep)


class BrickEmitPulse: public BrickEmitBase {
	MBRICK(BrickEmitPulse)
	BrickEmitPulse(double ampl = 1., double period = 1., double duration = 0.5, double offset = 0.): BrickEmitBase(4, 1) {setParameters(ampl, period, duration, offset); type = "Pulse"; setName(type); inNames[0] = "Amplitude"; inNames[1] = "Period, s"; inNames[2] = "Duration, s"; inNames[3] = "Start Delay, s";}
	enum Inputs {Amplitude, Period, Duration, StartDelay};
	void setParameters(double ampl, double period, double duration, double offset) {inputs[Amplitude] = ampl; inputs[Period] = period; inputs[Duration] = duration; inputs[StartDelay] = offset;}
	virtual bool tick_body(double time);
};
ADD_NEW_TO_COLLECTION(Emitters, BrickEmitPulse)


class BrickEmitStrobe: public BrickEmitBase {
	MBRICK(BrickEmitStrobe)
	BrickEmitStrobe(): BrickEmitBase(0, 1) {type = "Strobe"; setName(type);}
	virtual bool tick_body(double time) {outputs[0] = 1. - outputs[0]; return true;}
};
ADD_NEW_TO_COLLECTION(Emitters, BrickEmitStrobe)


class BrickEmitTime: public BrickEmitBase {
	MBRICK(BrickEmitTime)
	BrickEmitTime(): BrickEmitBase(0, 1) {type = "Time"; setName(type);}
	virtual bool tick_body(double time) {outputs[0] = time; return true;}
};
ADD_NEW_TO_COLLECTION(Emitters, BrickEmitTime)


class BrickEmitFrequency: public BrickEmitBase {
	MBRICK(BrickEmitFrequency)
	BrickEmitFrequency(): BrickEmitBase(0, 1) {type = "Frequency"; setName(type);}
	virtual bool tick_body(double time) {outputs[0] = manager_->freq; return true;}
};
ADD_NEW_TO_COLLECTION(Emitters, BrickEmitFrequency)


class BrickEmitNoiseRandom: public BrickEmitBase {
	MBRICK(BrickEmitNoiseRandom)
	BrickEmitNoiseRandom(double shift = 0., double scale = 1.): BrickEmitBase(2, 1) {setParameters(shift, scale); type = "Random"; setName(type); inNames[0] = "Shift"; inNames[1] = "Scale";}
	enum Inputs {Shift, Scale};
	void setParameters(double shift, double scale) {inputs[Shift] = shift; inputs[Scale] = scale;}
	virtual bool tick_body(double time) {outputs[0] = randomd() * inputs[Scale] + inputs[Shift]; return true;}
};
ADD_NEW_TO_COLLECTION(Emitters, BrickEmitNoiseRandom)


class BrickEmitNoiseNormal: public BrickEmitBase {
	MBRICK(BrickEmitNoiseNormal)
	BrickEmitNoiseNormal(double shift = 0., double scale = 1.): BrickEmitBase(2, 1) {setParameters(shift, scale); type = "NormalNoise"; setName(type); inNames[0] = "Shift"; inNames[1] = "Scale";}
	enum Inputs {Shift, Scale};
	void setParameters(double shift, double scale) {inputs[Shift] = shift; inputs[Scale] = scale;}
	virtual bool tick_body(double time) {outputs[0] = randomn(inputs[Shift], inputs[Scale]); return true;}
};
ADD_NEW_TO_COLLECTION(Emitters, BrickEmitNoiseNormal)

#endif // BRICK_EMITS_H
