#ifndef CONNECTIONWRAP_H
#define CONNECTIONWRAP_H
#include <string>
#include "Connection.h"
#include "FilterConnection.h"
#include "ConfigConnection.h"
union ConnectionU {
	Connection<char> * charConn;
	Connection<double> * doubleConn;
	Connection<float> * floatConn;
	Connection<short> * shortConn;
	FilterConnection<char>  * charFConn;
	FilterConnection<double>* doubleFConn;
	FilterConnection<float> * floatFConn;
	FilterConnection<short> * shortFConn;
	ConfigConnection        * configConn;
	void * voidStar;
} typedef ConnectionU;
#define SHORTCONN 0
#define CHARCONN  1
#define BYTECONN  1
#define FLOATCONN 2
#define DOUBLECONN 3
#define CONFIGCONN 4
class ConnectionWrap { //5 bytes Not too bad
	public:
	ConnectionU conn;
	char type;
	ConnectionWrap() {}
	ConnectionWrap(void * connection,int type) {
		conn.voidStar = connection;
		this->type = (char)type;
	}
	inline int getFileHandle() {
		if (type==SHORTCONN) {
			return conn.shortConn->getFileHandle();
		} else if (type==CHARCONN) {
			return conn.charConn->getFileHandle();
		} else if (type==FLOATCONN) {
			return conn.floatConn->getFileHandle();
		} else if (type==DOUBLECONN) {
			return conn.doubleConn->getFileHandle();
		}
		return 0;
	}
	inline bool readable() {
		if (type==SHORTCONN) {
			return conn.shortConn->readable();
		} else if (type==CHARCONN) {
			return conn.charConn->readable();
		} else if (type==FLOATCONN) {
			return conn.floatConn->readable();
		} else if (type==DOUBLECONN) {
			return conn.doubleConn->readable();
		}
		return 0;
	}
	inline string * getXML() {
		if (type==SHORTCONN) {
			return conn.shortFConn->getXML();
		} else if (type==CHARCONN) {
			return conn.charFConn->getXML();
		} else if (type==FLOATCONN) {
			return conn.floatFConn->getXML();
		} else if (type==DOUBLECONN) {
			return conn.doubleFConn->getXML();
		}
		return 0;
	}
	inline void disconnect() {
		if (type==SHORTCONN) {
			return conn.shortConn->disconnect();
		} else if (type==CHARCONN) {
			return conn.charConn->disconnect();
		} else if (type==FLOATCONN) {
			return conn.floatConn->disconnect();
		} else if (type==DOUBLECONN) {
			return conn.doubleConn->disconnect();
		}
	}
	inline void process() {
		if (type==SHORTCONN) {
			conn.shortFConn->process();
		} else if (type==CHARCONN) {
			conn.charFConn->process();
		} else if (type==FLOATCONN) {
			conn.floatFConn->process();
		} else if (type==DOUBLECONN) {
			conn.doubleFConn->process();
		}
	}
	inline ~ConnectionWrap() {
		if (type==SHORTCONN) {
			delete conn.shortConn;
		} else if (type==CHARCONN) {
			delete conn.charConn;
		} else if (type==FLOATCONN) {
			delete conn.floatConn;
		} else if (type==DOUBLECONN) {
			delete conn.doubleConn;
		}
	}
	inline void disconnectFrom(ConnectionWrap * w) {
		if (type==SHORTCONN && w->type ==SHORTCONN) {
			((FilterConnection<short>*)(conn.shortConn))->disconnectFrom(*(Connection<short>*)w->conn.shortConn);
		} else if (type==CHARCONN && w->type==CHARCONN) {
			return ((FilterConnection<char>*)(conn.charConn))->disconnectFrom(*(Connection<char>*)w->conn.charConn);
		} else if (type==FLOATCONN && w->type==FLOATCONN) {
			return ((FilterConnection<float>*)(conn.floatConn))->disconnectFrom(*(Connection<float>*)w->conn.floatConn);
		} else if (type==DOUBLECONN && w->type==DOUBLECONN) {
			return ((FilterConnection<double>*)(conn.doubleConn))->disconnectFrom(*(Connection<double>*)w->conn.doubleConn);
		} else {
			throw new string("Connections are of different data types!");
		}
	}
	inline void connectFrom(ConnectionWrap * w) {
		if (type==SHORTCONN && w->type ==SHORTCONN) {
			((FilterConnection<short>*)(conn.shortConn))->connectFrom(*(Connection<short>*)w->conn.shortConn);
		} else if (type==CHARCONN && w->type==CHARCONN) {
			return ((FilterConnection<char>*)(conn.charConn))->connectFrom(*(Connection<char>*)w->conn.charConn);
		} else if (type==FLOATCONN && w->type==FLOATCONN) {
			return ((FilterConnection<float>*)(conn.floatConn))->connectFrom(*(Connection<float>*)w->conn.floatConn);
		} else if (type==DOUBLECONN && w->type==DOUBLECONN) {
			return ((FilterConnection<double>*)(conn.doubleConn))->connectFrom(*(Connection<double>*)w->conn.doubleConn);
		} else {
			throw new string("Connections are of different data types!");
		}
	}
};
#endif

