
// Title:	Block.h

#ifndef BLOCK_H
	#define BLOCK_H					// inclusion guard

	// User defined consts/vars.

	// User defined types
	enum EBlockShape {e_elipse, e_rectangle, e_triangle};						// block shapes
	enum EDirection {e_left, e_right, e_up, e_down};							// block direction (triangle specific)
	enum EIntegrationMethod {e_Euler, e_RungeKutta};							// integration schemes, (Euler) 1st and (RK) 4th order
	enum EMultAction {e_element_wise, e_mat_x_input, e_input_x_mat, e_divide};	// multiplication action, form and order
	enum EOutputDataFormat {e_dep_var, e_dep_and_indep_var};					// form of output: dependent and independent vars
	enum EPortID {e_left_arrow, e_up_arrow, e_right_arrow, e_down_arrow};		// left '<', up '^', right '>', and, down 'v'
	enum ESignalForm {e_sine, e_cosine, e_square, e_sawtooth, e_random};		// form of signal/wave
	enum EUnits {e_m, e_s, e_kg, e_radians, e_hertz, e_radians_per_sec};		// units

	// BlockShape
	class CBlockShape
	{
	public:
		CBlockShape(void);
		~CBlockShape(void);
	
	private:
		double geometry[3];		// square (l,w,thick), circle (r,d,thick), triangle (l,direc,thick)
		EBlockShape m_eBlockShape;
	};

	// Port
	class CBlock;				// predefining CBlock as it's rqd. by CPort, additionally CBlock rqes. CPort
	class CPort
	{
	public:
		CPort(CBlock &block_ref);
		~CPort(void);

		// Accessor methods
		char *GetName(void);
	
	private:
		char	*port_name;			// name of either input or output port
		double	port_position[2];	// ordered pair denoting (x,y) location of port w.r.t. block CofM
		CBlock	&m_rRefToBlock;		// reference to its parent/own block upon which the port resides
		EPortID e_port_id;			// '>' arrow pts away/towards block center for output/input (left, up, right, down)
	};

	// Block
	class CSystemModel;			// predefining CSystemModel as it's rqd. by CBlock, additionally CSystemModel rqes. CBlock
	class CBlock
	{
	public:
		CBlock(void);
		~CBlock(void);

		// Accessor methods
		char* GetName(void);
	
	private:
		char			*block_name;			
		double			block_position[2];		// ordered pair denoting (x,y) location of CofM of block
		CBlockShape		m_BlockShape;			// member obj of type CBlockShape
		vector<CPort*>	m_vecInputPorts;		// vector of ptrs to CPort
		vector<CPort*>	m_vecOutputPorts;		// vector of ptrs to CPort
		CSystemModel	*m_pParentSystemModel;	// prt to parent system model
		CSystemModel	*m_pSubSystemModel;		// ptr = NULL => no contained system/sub model, ptr != NULL => system model
	};

	// ConstantBlock
	class CConstantBlock : public CBlock
	{
	public:
		CConstantBlock(void);
		~CConstantBlock(void);

	private:
		double scalar_const;
		double *vector_const;
		double **matrix_const;
	};

	// DerivativeBlock
	class CDerivativeBlock : public CBlock
	{
	public:
		CDerivativeBlock(void);
		~CDerivativeBlock(void);

	private:
		int		derivative_method;		// 3-pt method, 5-pt method
		double	t_step_size_h;			// time step size 'h' used in the defn of the numerical derivative
	};

	// DivideBlock
	class CDivideBlock : public CBlock
	{
	public:
		CDivideBlock(void);
		~CDivideBlock(void);

	private:
		int m_iNMultiplyInputs;			// no. of multiplication inputs
		int m_iNDivideInputs;			// no. of division inputs
		EMultAction e_mult_action;		// if divide used for a matrix, then matrix inverse is rqd.
	};

	// GainBlock
	class CGainBlock : public CBlock
	{
	public:
		CGainBlock(void);
		~CGainBlock(void);

	private:
		double scalar_gain;
		double *vector_gain;
		double **matrix_gain;
		EMultAction e_mult_action;
	};

	// IntegratorBlock
	class CIntegratorBlock : public CBlock
	{
	public:
		CIntegratorBlock(void);
		~CIntegratorBlock(void);

	private:
		double t_step_size_h;		// time step size "h"
		double *ic_vector;			// initial condition vector
		EIntegrationMethod e_integration_method;
	};

	// LinearFnBlock
	class CLinearFnBlock : public CBlock	
	{
	public:
		CLinearFnBlock(void);
		~CLinearFnBlock(void);

	private:
		double fn_derivative;	// slope of linear fn or "curve"
		double signal_init_val;	// init val of signal (at time t0)
		double t_signal_start;	// start time of signal
	};

	// OutputBlock
	class COutputBlock : public CBlock
	{
	public:
		COutputBlock(void);
		~COutputBlock(void);

	private:
		char	*file_name;
		double	t_start;
		double	t_stop;
		EOutputDataFormat e_data_format;
	};

	// SignalGeneratorBlock
	class CSignalGeneratorBlock : public CBlock
	{
	public:
		CSignalGeneratorBlock(void);
		~CSignalGeneratorBlock(void);

	private:		// externally generated signal is being ignored for now.
		double		amplitude;
		double		frequency;
		EUnits		e_units;
		ESignalForm e_signal_form;
	};

	// SubsystemBlock
	class CSubsystemBlock : public CBlock
	{
	public:
		CSubsystemBlock(void);
		~CSubsystemBlock(void);

	private:
		int			port_number_label_1;		// number to appear as the port label
		int			port_number_label_2;		// number to appear as the port label
		char		*port_signal_label_1;		// signal identifier (name) to appear as the port label
		char		*port_signal_label_2;		// signal identifier (name) to appear as the port label
	};

	// SubsystemInBlock
	class CSubsystemInBlock : public CBlock
	{
	public:
		CSubsystemInBlock(void);
		~CSubsystemInBlock(void);

	private:
		int			port_number_label;		// number to appear as the port label
		char		*port_signal_label;		// signal identifier (name) to appear as the port label
	};

	// SubsystemOutBlock
	class CSubsystemOutBlock : public CBlock
	{
	public:
		CSubsystemOutBlock(void);
		~CSubsystemOutBlock(void);

	private:
		int			port_number_label;		// number to appear as the port label
		char		*port_signal_label;		// signal identifier (name) to appear as the port label
	};

	// SumBlock
	class CSumBlock : public CBlock
	{
	public:
		CSumBlock(void);
		~CSumBlock(void);

	private:
		int no_of_plus_inputs;
		int no_of_minus_inputs;
	};

	// TransferFnBlock
	class CTransferFnBlock : public CBlock
	{
	public:
		CTransferFnBlock(void);
		~CTransferFnBlock(void);

	private:
		double *numerator_coeffs_vec;		// vector of numerator coeffs
		double *denominator_coeffs_vec;		// vector of denominator coeffs
	};

#endif

// eof