using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.Networking.Types;

public class Server : MonoBehaviour {

	List<Tuple<int, string, int>> servers;
	List<int> clients;

	int hostID;
	int selfChannelID;

	// Use this for initialization
	void Start () {
		servers = new List<Tuple<int, string, int>>();
		clients = new List<int>();

		NetworkTransport.Init();
		ConnectionConfig config = new ConnectionConfig();
		selfChannelID  = config.AddChannel(QosType.ReliableSequenced);
		HostTopology topology = new HostTopology(config, 10);
		hostID = NetworkTransport.AddHost(topology, 49610);
	}
	
	// Update is called once per frame
	void Update () {
		int recHostID; 
		int connectionID; 
		int channelID; 
		byte[] recBuffer = new byte[1024]; 
		int bufferSize = 1024;
		int dataSize;
		byte error;
		NetworkEventType recData = NetworkTransport.Receive(out recHostID, out connectionID, out channelID, recBuffer, bufferSize, out dataSize, out error);

		int port;
		string ip;

		NetworkID networkID;
		NodeID nodeID;
		NetworkTransport.GetConnectionInfo(recHostID, connectionID, out ip, out port, out networkID, out nodeID, out error);

		if (ip.Length > 7) {
			ip = ip.Remove(0, 7); //remove ::ffff:
		}

		switch (recData)
		{
			case NetworkEventType.ConnectEvent:
				/*
				int port;
				string ip;

				NetworkID networkID;
				NodeID nodeID;

				NetworkTransport.GetConnectionInfo(recHostID, connectionID, out ip, out port, out networkID, out nodeID, out error);

				ip = ip.Remove(0, 7); //remove ::ffff:

				Debug.Log("Connection from " + ip + ":" + port);*/
			break;
				
			case NetworkEventType.DataEvent:
				Buffer inputBuffer = new Buffer(recBuffer);

				int code = inputBuffer.readInt();

				switch(code) {
					case 0:
						string message = inputBuffer.readString();

						Debug.Log(message);

					break;
					case 2:
						bool isServer = inputBuffer.readBool();

						if (isServer) {
							

							servers.Add(new Tuple<int, string, int>(connectionID, ip, port));

							//Send new info the connected clients
							Buffer buffer = new Buffer();
							buffer.writeInt(1);
							buffer.writeString(ip);
							buffer.writeInt(port);
							foreach(int client in clients) {
								NetworkTransport.Send(hostID, client, channelID, buffer.getArray(), buffer.getLength(), out error);
							}
						}
						else {
							clients.Add(connectionID);

							foreach(Tuple<int, string, int> tuple in servers) {

								Buffer buffer = new Buffer();
								buffer.writeInt(1);
								buffer.writeString(tuple._2);
								buffer.writeInt(tuple._3);

								NetworkTransport.Send(hostID, connectionID, channelID, buffer.getArray(), buffer.getLength(), out error);
							}
						}

					break;
					case 3:
						string serverIP = inputBuffer.readString();
						int serverPort = inputBuffer.readInt();
						foreach(Tuple<int, string, int> tuple in servers) {
							if (tuple._2 == serverIP && tuple._3 == serverPort) {
								Buffer buffer = new Buffer();
								buffer.writeInt(4);
								buffer.writeString(ip);
								buffer.writeInt(port);

								NetworkTransport.Send(hostID, tuple._1, channelID, buffer.getArray(), buffer.getLength(), out error);
							}
						}
					break;
				}
			break;

			case NetworkEventType.DisconnectEvent:
				clients.Remove(connectionID);
				servers.RemoveAll(tuple => tuple._1 == connectionID);

				//TODO : Send packet which removes server from client's lists
			break;
		}
	}

	void OnGUI() {
		for(int i = 0; i < servers.Count; i++) {
			GUI.Label(new Rect(10, 10 + i * 30, 150, 20), servers[i]._2 + " : " + servers[i]._3);
		}
		for(int i = 0; i < clients.Count; i++) {
			GUI.Label(new Rect(1000, 10 + i * 30, 150, 20), clients[i] + "");
		}
	}
}
