#ifndef BRICK_LINK_H
#define BRICK_LINK_H

#include "brick_math.h"


class BrickLinkBase: public BrickBase {
public:
	BrickLinkBase(int inputs_num = 1, int outputs_num = 1, int parameters_num = 0): BrickBase(inputs_num, outputs_num, parameters_num + 1) {
		lib = "Links";
		paramNames[0] = "Method";
		parameters[0].setValue(-1);
		note_ = "Methods description you can find in help content.";//PIMathSolver::methods_desc;
	}
};


class BrickLinkTransferFunction: public BrickLinkBase {
	MBRICK(BrickLinkTransferFunction)
	BrickLinkTransferFunction(const PIString & num = "1", const PIString & denom = "1 1");
	virtual void parameterChanged(int index);
	virtual void reset_specified() {started();}
	virtual void started() {parameterChanged(1); KF.fromTF(TF);}
	virtual bool tick_body(double time);
private:
	void copied() {reset_specified();}
	PIMathSolver KF;
	TransferFunction TF;
};


class BrickLinkFilter1Degree: public BrickLinkBase {
	MBRICK(BrickLinkFilter1Degree)
	BrickLinkFilter1Degree(double t = 1., double k = 1.);
	virtual void reset_specified() {s.reset(); a.reset(); i.reset(); i.setInputValue(1, 1.);}
	enum Inputs {Input, T, K};
	enum Outputs {LowPass, HighPass};
	void setParameters(double t, double k) {inputs[T] = t; inputs[K] = k;}
	virtual void started() {parameterChanged(0);}
	virtual bool tick_body(double time);
	virtual void parameterChanged(int index) {i.setParameterValue(index, parameters[index]);}
private:
	void copied() {clearConnections(); makeConnections();}
	void clearConnections() {s.clearConnections(); a.clearConnections(); i.clearConnections();}
	void makeConnections() {connect(s, 0, a, BrickMathAmplifier::Input); BrickBase::connect(a, 0, i, 0); BrickBase::connect(i, 0, s, 1);}
	BrickMathSum s;
	BrickMathAmplifier a;
	BrickMathIntegral i;
};
ADD_NEW_TO_COLLECTION(Links, BrickLinkFilter1Degree)


class BrickLinkFilterBandpass: public BrickLinkBase {
	MBRICK(BrickLinkFilterBandpass)
	BrickLinkFilterBandpass(double lf = 1., double hf = 2.);
	enum Inputs {Input, LF, HF};
	inline void setParameters(double lf, double hf) {inputs[LF] = lf; inputs[HF] = hf;}
	virtual void parameterChanged(int index) {KF.setMethod((PIMathSolver::Method)parameters[0].toInt());}
	virtual void reset_specified() {started();}
	virtual void started() {pl = ph = 0.; setParameters(inputs[LF], inputs[HF]); KF.fromTF(TF);}
	virtual bool tick_body(double time);
private:
	double pl, ph, t0, t1;
	PIMathSolver KF;
	TransferFunction TF;
};
ADD_NEW_TO_COLLECTION(Links, BrickLinkFilterBandpass)


class BrickLinkFilterMedian: public BrickLinkBase {
	MBRICK(BrickLinkFilterMedian)
	BrickLinkFilterMedian(int count = 3);
	inline void setParameters(int count) {parameters[0].setValue(piMaxi(count, 0)); hist_.resize(count);}
	virtual void parameterChanged(int index) {hist_.resize(parameters[0].toInt()); hsort.resize(hist_.size());}
	virtual void reset_specified() {started();}
	virtual void started() {hist_.fill(0.);}
	virtual bool tick_body(double time);
private:
	PIVector<double> hist_, hsort;
};
ADD_NEW_TO_COLLECTION(Links, BrickLinkFilterMedian)

#endif // BRICK_LINK_H
