#include "dispatcherclient.h"
#include "picloudtcp.h"


DispatcherClient::DispatcherClient(PIEthernet * eth_, int id) : authorised(false), eth(eth_), streampacker(eth_), tcp(&streampacker), client_id(id) {
	CONNECTU(&disconnect_tm, tickEvent, eth, close);
	CONNECTU(&streampacker, packetReceiveEvent, this, readed);
	CONNECTU(eth, disconnected, this, disconnected);
	piCoutObj << "client connected" << eth->sendAddress();
}


void DispatcherClient::start() {
	eth->startThreadedRead();
	//disconnect_tm.start(10000);
}


DispatcherClient::~DispatcherClient() {
//	delete eth;
}


PIString DispatcherClient::address() {
	return eth->path();
}

void DispatcherClient::close() {
	eth->close();
}


void DispatcherClient::sendConnected(uint client_id) {
	//piCoutObj << "sendConnected";
	tcp.sendConnected(client_id);
}


void DispatcherClient::sendDisconnected(uint client_id) {
	tcp.sendDisconnected(client_id);
}


void DispatcherClient::sendData(const PIByteArray & data) {
	if (tcp.role() == PICloud::TCP::Client) tcp.sendData(data);
	else piCoutObj << "error sendData, invalid role";
}


void DispatcherClient::sendDataToClient(const PIByteArray & data, uint client_id) {
	if (tcp.role() == PICloud::TCP::Server) tcp.sendData(data, client_id);
	else piCoutObj << "error sendDataToClient, invalid role";
}


void DispatcherClient::authorise(bool ok) {
	authorised = ok;
}


void DispatcherClient::disconnected(bool withError) {
	//piCoutObj << "client disconnected" << eth->sendAddress();
	disconnectEvent(this);
}


void DispatcherClient::readed(PIByteArray & ba) {
//	piCout << size;
	PIPair<PICloud::TCP::Type, PICloud::TCP::Role> hdr = tcp.parseHeader(ba);
	if (hdr.first == PICloud::TCP::InvalidType) {
		disconnected(true);
		return;
	}
	if (authorised) {
		if (hdr.second == tcp.role()) {
			switch (hdr.first) {
			case PICloud::TCP::Connect:
			return;
			case PICloud::TCP::Disconnect:
				disconnected(false);
			return;
			case PICloud::TCP::Data:
//				piCoutObj << "TCP::Data";
				if (tcp.role() == PICloud::TCP::Client) {
					PIByteArray data = tcp.parseData(ba);
					if (!data.isEmpty()) dataReaded(data);
					else piCoutObj << "invalid data from client";
				}
				if (tcp.role() == PICloud::TCP::Server) {
					PIPair<uint, PIByteArray> dp = tcp.parseDataServer(ba);
					if (!dp.second.isEmpty()) dataReadedServer(dp.first, dp.second);
					else piCoutObj << "invalid data from server";
				}
			return;
			default:
				//disconnected(true);
			return;
			}
		}
	} else {
		switch (hdr.first) {
		case PICloud::TCP::Connect: {
			tcp.setRole(hdr.second);
			PIByteArray sn = tcp.parseConnect_d(ba);
			if (hdr.second == PICloud::TCP::Server) registerServer(sn, this);
			if (hdr.second == PICloud::TCP::Client) registerClient(sn, this);
			return;}
		case PICloud::TCP::Disconnect:
			disconnected(false);
		return;
		default:
			disconnected(true);
		return;
		}
	}
}

