#include <QTcpServer>
#include <vector>
#include <QTcpSocket>
#include <QJsonArray>

#include "items/item.h"
#include "server.h"
#include "tcpserver.h"

TcpServer::TcpServer(QObject* parent):
	Server(parent),
	server(this)
{
	connect(&server, &QTcpServer::newConnection, this, &TcpServer::incomingConnection);
}

void TcpServer::sendJson(const QJsonObject& json)
{
	for(auto& client: clients)
	{
		if(client.socket.tcpSocket) {
			QByteArray jsonData = QJsonDocument(json).toJson();
			client.socket.tcpSocket->write(QString("MSG JSON LEN " + QString::number(jsonData.size()) + "\n").toLatin1() + jsonData);
		}
	}
}

void TcpServer::processIncomeingJson(const QByteArray& jsonbytes)
{
	Server::processIncomeingJson(jsonbytes);
}

bool TcpServer::launch(const QHostAddress &address, quint16 port)
{
	qInfo()<<"Tcp server launched on"<<address<<"port"<<port;
	return server.listen(address, port);
}

void TcpServer::incomingConnection()
{
	while(server.hasPendingConnections())
	{
		QTcpSocket* client = server.nextPendingConnection();
		qDebug()<<"Got new client from"<<client->peerAddress().toString();
		if(client)
		{
			Client c;
			c.socket.tcpSocket = client;
			clients.push_back(c);
			connect(client, &QTcpSocket::errorOccurred, this, [this, client]() { removeClient(client); });
			connect(client, &QTcpSocket::disconnected, this, [this, client]() { removeClient(client); });
			connect(client, &QTcpSocket::readyRead, this, &TcpServer::socketReadyRead);
		}
	}
}

void TcpServer::processComand(const QByteArray& command, Client& client)
{
	if(command.startsWith("MSG JSON LEN "))
	{
		client.state = STATE_RECV_JSON;
		client.recievebytes = command.mid(13).toLongLong();
		qDebug()<<"Got command:"<<QString::fromLatin1(command);
	}
}

void TcpServer::socketReadyRead()
{
	for(size_t i = 0; i < clients.size(); i++)
	{
		QTcpSocket* tcp = clients[i].socket.tcpSocket;
		if(tcp && tcp == sender())
		{
			QByteArray newChars = tcp->readAll();
			clients[i].buffer += newChars;

			bool remianing = true;
			while(remianing)
			{
				remianing = false;
				while(clients[i].state == STATE_IDLE && clients[i].buffer.contains('\n'))
				{
					size_t newlineIndex = clients[i].buffer.indexOf('\n');
					QByteArray command = clients[i].buffer.left(newlineIndex);
					clients[i].buffer.remove(0, newlineIndex+1);
					processComand(command, clients[i]);
					remianing = true;
				}
				if(clients[i].state == STATE_RECV_JSON)
				{
					if(clients[i].recievebytes <= clients[i].buffer.size())
					{
						QByteArray json = clients[i].buffer.left(clients[i].recievebytes);
						clients[i].buffer.remove(0, clients[i].recievebytes);
						clients[i].recievebytes = 0;
						clients[i].state = STATE_IDLE;
						processIncomeingJson(json);
						remianing = true;
					}
				}
			}
		}
	}
}
