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

public abstract class Requests {
	//==============================================================================
	//Template
	//==============================================================================

	/*
	public static void template(NetworkReader message) {
		RequestTemplateBuffer buffer = message.ReadMessage<RequestTemplateBuffer>();
		Requests.template(buffer.args);
	}

	public static void template(args) {
		if (NetworkManager.isServer()) {
			//Send update to clients
			TemplateBuffer buffer = new TemplateBuffer();
			buffer.args = args;
			buffer.sendToAllAndExecute();
		}
		else {
			//Send request to server
			RequestTemplateBuffer buffer = new RequestTemplateBuffer();
			buffer.args = args;
			buffer.sendToServer();
		}
	}
	*/

	//==============================================================================
	//Message
	//==============================================================================

	public static void sendMessage(NetworkReader message) {
		RequestMessageBuffer buffer = message.ReadMessage<RequestMessageBuffer>();
		Requests.sendMessage(buffer.message);
	}

	public static void sendMessage(string message) {
		if (NetworkManager.isServer()) {
			//Send update to clients
			MessageBuffer buffer = new MessageBuffer();
			buffer.message = message;
			buffer.sendToAllAndExecute();
		}
		else {
			//Send request to server
			RequestMessageBuffer buffer = new RequestMessageBuffer();
			buffer.message = message;
			buffer.sendToServer();
		}
	}

	//==============================================================================
	//Move
	//==============================================================================

	public static void move(NetworkReader message, int connectionID) {
		RequestMoveBuffer buffer = message.ReadMessage<RequestMoveBuffer>();
		//Requests.move(buffer.id, buffer.position, buffer.speed, buffer.rotation, message.conn.connectionId);
		Requests.move(buffer.id, buffer.position, buffer.speed, buffer.rotation, connectionID);
	}

	public static void move(GameObject obj) {
		Requests.move(obj.GetComponent<SharedGameObject>().id, 
			new Vector2(obj.transform.localPosition.x, obj.transform.localPosition.y),
			obj.GetComponentInChildren<Rigidbody2D>().velocity, obj.GetComponentInChildren<Rigidbody2D>().rotation);
	}

	private static void move(int id, Vector2 position, Vector2 speed, float rotation, int connectionID = -1) {
		MoveBuffer moveBuffer = new MoveBuffer();
		moveBuffer.id = id;
		moveBuffer.position = position;
		moveBuffer.speed = speed;
		moveBuffer.rotation = rotation;
		if (NetworkManager.isServer()) {
			//Send update to clients
			moveBuffer.sendToNonOwnerAndExecute(connectionID);
		}
		else {
			//Send request to server
			RequestMoveBuffer requestBuffer = new RequestMoveBuffer();
			requestBuffer.id = id;
			requestBuffer.position = position;
			requestBuffer.speed = speed;
			requestBuffer.rotation = rotation;
			requestBuffer.sendToServer();

			//Only for moves
			Actions.move(moveBuffer);
		}
	}

	//==============================================================================
	//EVA
	//==============================================================================

	public static void EVA(NetworkReader message) {
		RequestEVABuffer buffer = message.ReadMessage<RequestEVABuffer>();
		Requests.EVA(buffer.id);
	}

	public static void EVA(int id) {
		if (Time.realtimeSinceStartup - GameController.timeChangedEVA < 1)
			return;
		GameController.timeChangedEVA = Time.realtimeSinceStartup;

		if (NetworkManager.isServer()) {
			//Send update to clients
			EVABuffer buffer = new EVABuffer();
			buffer.id = id;
			buffer.sendToAllAndExecute();
		}
		else {
			//Send request to server
			RequestEVABuffer buffer = new RequestEVABuffer();
			buffer.id = id;
			buffer.sendToServer();
		}
	}

	//==============================================================================
	//Spawn
	//==============================================================================
	public static int spawn(ObjectType type, int index, Vector2 position, float rotation, int parentSpaceShipID = -1) {
		if (NetworkManager.isServer()) {
			//Send update to clients
			SpawnBuffer buffer = new SpawnBuffer();
			buffer.type = type;
			buffer.index = index;
			buffer.position = position;
			buffer.rotation = rotation;
			buffer.id = SharedGameObject.nextID++;
			buffer.parentSpaceShipID = parentSpaceShipID;
			buffer.sendToAllAndExecute();
			return buffer.id;
		}
		else {
			//Clients cannot request spawn
			Debug.Assert(false);
		}

		return -1;
	}

	//==============================================================================
	//Change Controller
	//==============================================================================

	public static void changeController(NetworkReader message) {
		RequestControllerChangeBuffer buffer = message.ReadMessage<RequestControllerChangeBuffer>();
		Requests.changeController(buffer.gameObjectID, buffer.internalControllerID, buffer.playerID);
	}

	public static void changeController(int gameObjectID, int internalControllerID, int playerID = -1) {
		if (playerID == -1)
			playerID = GameController.player.id;

		if (NetworkManager.isServer()) {
			//TODO: check if occupied

			//Send update to clients
			ControllerChangeBuffer buffer = new ControllerChangeBuffer();
			buffer.gameObjectID = gameObjectID;
			buffer.internalControllerID = internalControllerID;
			buffer.playerID = playerID;
			buffer.sendToAllAndExecute();
		}
		else {
			//Send request to server
			RequestControllerChangeBuffer buffer = new RequestControllerChangeBuffer();
			buffer.gameObjectID = gameObjectID;
			buffer.internalControllerID = internalControllerID;
			buffer.playerID = playerID;
			buffer.sendToServer();
		}
	}

	//==============================================================================
	//New Player
	//==============================================================================

	public static void newPlayer(int characterID, int connectionID) {
		if (NetworkManager.isServer()) {
			//Send update to clients
			NewPlayerBuffer buffer = new NewPlayerBuffer();
			buffer.playerID = Player.nextID++;
			buffer.characterID = characterID;
			buffer.isSelf = false;

			if (connectionID == -1) {
				buffer.sendToAll();

				buffer.isSelf = true;
				Actions.newPlayer(buffer);
			}
			else {
				buffer.sendToNonNewAndExecute(connectionID);

				buffer.isSelf = true;
				buffer.sendToClient(connectionID);
			}
		}
		else {
			//Clients cannot request new player
			Debug.Assert(false);
		}
	}
}
