#include "pip.h"

class Client: public PIObject {
	PIOBJECT(Client)

public:
	Client(PIEthernet * eth_) {
		eth = eth_;
		eth->startThreadedRead();
		CONNECT2(void, const uchar *, ssize_t, eth, threadedReadEvent, this, readed);
		CONNECT1(void, bool, eth, disconnected, this, disconnected);
		piCoutObj << uint(eth) << "client connected";
	}
	~Client() {}
	EVENT_HANDLER2(void, readed, const uchar *, data, ssize_t, size) {
		PIByteArray ba(data, size);
		piCoutObj << uint(eth) << "readed" << size << "bytes" << PICoutManipulators::Hex << ba;
		eth->write(ba);
	}
	EVENT_HANDLER1(void, disconnected, bool, withError) {
		piCoutObj << uint(eth) << "client disconnected";
		disconnect(this);
	}
	void send() {
		PIByteArray ba;
		ba << uchar(0) << uchar(1) << uchar(2);
		piCoutObj << uint(eth) << "client send" << ba;
		eth->write(ba);
	}
	PIEthernet * eth;

	EVENT1(disconnect, Client *, client)
};

class Server: public PIObject {
	PIOBJECT(Server)

public:
	Server(int port) {
		eth = new PIEthernet(PIEthernet::TCP_Server);
		eth->setParameter(PIEthernet::ReuseAddress);
		CONNECT1(void, PIEthernet *, eth, newConnection, this, newConnection);
		PIString path = "0.0.0.0:" + PIString::fromNumber(port);
		eth->listen(path, true);
		piCoutObj << uint(eth) << "server started" << path;
	}
	~Server() {
		eth->close();
		piCoutObj << uint(eth) << "server stoped";
		delete eth;
	}
	EVENT_HANDLER1(void, newConnection, PIEthernet *, cl) {
		piCoutObj << uint(eth) << "add client";
		Client * client = new Client(cl);
		CONNECT1(void, Client *, client, disconnect, this, disconnect);
		clients.push_back(client);
	}
	EVENT_HANDLER1(void, disconnect, Client *, client) {
		piCoutObj << uint(eth) << "remove client";
		delete client;
		clients.removeOne(client);
	}
	PIEthernet * eth;
	PIVector<Client *> clients;
	void send() {
		for (int i = 0; i < clients.size(); i++) {
			clients[i]->send();
		}
	}
};

Server sl(10001);
Server s2(10002);


void keyEvent(char key, void *) {
	switch (key) {
	case '1': sl.send(); break;
	case '2': s2.send(); break;
	};
};

void timerEvent(void *, int){
	// sl.send();
};

PITimer timer(timerEvent);

int main(int argc, char * argv[]) {
	timer.start(1000.);
	PIKbdListener kbd(keyEvent);
	kbd.enableExitCapture();
	WAIT_FOR_EXIT;
	return 0;
}
