using UnityEngine;
using System.Collections;

public class ClientWorld : MonoBehaviour {
	private Game game;

	public Transform rhinoPrefab; // inspector
	public Owl owlPrefab; // inspector
	public Transform poacherPrefab; // inspector
	public Transform treasurePrefab; // inspector
	public Transform foodPrefab; // inspector
	public Transform rampagingRhinoPrefab; // inspector
	public Transform madRhinoPrefab; // inspector
	public ParticleSystem poacherExplosionPrefab; // inspector
	public ParticleSystem rhinoExplosionPrefab; // inspector

	private Transform rhino;
	private Owl owl;

	public float movePrecision = 0.1F;
	private Vector3 rhinoTarget = Vector3.zero;
	private Vector3 rhinoVelocity = Vector3.zero;
	private Vector3 rhinoStep = Vector3.zero;

	private Hashtable poachers = new Hashtable();
	private Hashtable targets = new Hashtable();
	private Hashtable treasures = new Hashtable();
	private Hashtable foods = new Hashtable();
	private Hashtable rampagingRhinos = new Hashtable();
	private Hashtable rampagingTargets = new Hashtable();

	private bool firstUpdate = true;


	public void Init (Game game) {
		// spawn the rhino
		rhino = Instantiate (rhinoPrefab) as Transform;
		owl = Instantiate (owlPrefab) as Owl;

		Destroy(rhino.GetComponent<Rhino>());

		this.game = game;
		SetupCameraViewpointOwl();

		UpdateScore(0);
	}
	
	// Update is called once per frame
	void Update () {
		float diff = (rhinoTarget - rhino.transform.position).magnitude;
		// Move rhino
		if (diff > movePrecision)
		{
			rhino.transform.LookAt(rhinoTarget);
			rhino.transform.Translate(Vector3.forward * Time.deltaTime * diff);
		}

		// Move poachers
		foreach(int poacherID in poachers.Keys) {
			Transform poacher = poachers[poacherID] as Transform;
			Vector3 target = (Vector3) targets[poacherID];
			Vector3 diff2 = (target - poacher.position);
			if (diff2.magnitude > movePrecision) {
				poacher.position += (diff2 * Time.deltaTime * 1.5f);
			}
		}

		// Move rampaging rhinos
		foreach(int rampagingRhinoID in rampagingRhinos.Keys) {
			Transform rampagingRhino = rampagingRhinos[rampagingRhinoID] as Transform;
			Vector3 target = (Vector3) rampagingTargets[rampagingRhinoID];
			Vector3 diff2 = (target - rampagingRhino.position);
			if (diff2.magnitude > movePrecision) {
				rampagingRhino.position += (diff2 * Time.deltaTime * 1.5f);
			}
		}

		// Rotate food
		float dt = Time.deltaTime;
		foreach (int foodID in foods.Keys) {
			Transform food = foods[foodID] as Transform;
			food.Rotate (0f, 36f * dt, 0f);
		}
	}
	
	public Transform GetRhino() {
		return rhino;
	}

	public void SetRhinoTarget(Vector3 target) {
		rhinoTarget = target;
		if (firstUpdate) {
			owl.transform.position = new Vector3 (rhinoTarget.x, Data.owlHeight, rhinoTarget.z);
			firstUpdate = false;
		}
	}

	public void SetRhinoVelocity(Vector3 velocity) {
		rhinoVelocity = velocity;
	}

	public void SetupCameraViewpointOwl() {
		rhino.FindChild("Camera").camera.enabled = false;
		owl.camera.rect = new Rect (0f, 0f, 1f, 1f);
		owl.gameObject.AddComponent<FirstPersonOwlCamera>();
	}

	public void SpawnPoacher(int poacherID, Vector3 poacherPosition, Quaternion poacherRotation) {
		Transform poacher = Instantiate (poacherPrefab) as Transform;
		poacher.position = poacherPosition;
		poacher.rotation = poacherRotation;
		Destroy(poacher.GetComponent<Poacher>());
		poachers.Add (poacherID, poacher);
		targets.Add (poacherID, poacher.position);
	}

	public void KillPoacher(int poacherID) {
		if (poachers.ContainsKey(poacherID)) {
			Transform poacher = poachers[poacherID] as Transform;
			ParticleSystem explosion = Instantiate (poacherExplosionPrefab) as ParticleSystem;
			explosion.transform.position = poacher.position;
			poacher.rigidbody.constraints = RigidbodyConstraints.None;
		}
	}
	
	public void DestroyPoacher(int poacherID) {
		if (poachers.ContainsKey(poacherID)) {
			Transform poacher = poachers[poacherID] as Transform;
			Destroy (poacher.gameObject);
			poachers.Remove (poacherID);
			targets.Remove (poacherID);
		}
	}
	
	public void UpdatePoacher(int poacherID, Vector3 poacherPosition, Quaternion poacherRotation) {
		if (poachers.ContainsKey(poacherID)) {
			Transform poacher = poachers[poacherID] as Transform;
			poacher.rotation = poacherRotation;
			targets[poacherID] = poacherPosition;
		}
	}

	public void SpawnTreasure(int treasureID, Vector3 treasurePosition, Quaternion treasureRotation) {
		Transform treasure = Instantiate (treasurePrefab) as Transform;
		treasure.position = treasurePosition;
		treasure.rotation = treasureRotation;
		Destroy(treasure.GetComponent<Treasure>());
		//treasure.gameObject.AddComponent<ChildExploder> ();
		treasures.Add (treasureID, treasure);
	}
	
	public void DestroyTreasure(int treasureID) {
		if (treasures.ContainsKey(treasureID)) {
			Transform treasure = treasures[treasureID] as Transform;
			//treasure.gameObject.GetComponent<ChildExploder>().explode();
			treasure.FindChild ("Container").GetComponent<ChildExploder>().explode ();
			treasures.Remove (treasureID);
		}
	}

	public void SpawnFood(int foodID, Vector3 foodPosition, Quaternion foodRotation) {
		Transform food = Instantiate (foodPrefab) as Transform;
		food.position = foodPosition;
		food.rotation = foodRotation;
		Destroy(food.GetComponent<Food>());
		foods.Add (foodID, food);
	}
	
	public void DestroyFood(int foodID) {
		if (foods.ContainsKey(foodID)) {
			Transform food = foods[foodID] as Transform;
			foods.Remove (foodID);
			Destroy (food.gameObject);
		}
	}

	public void SpawnRampagingRhino(int rampagingRhinoID, Vector3 rampagingRhinoPosition, Quaternion rampagingRhinoRotation, bool isMad) {
		Transform rampagingRhino;
		if (isMad) {
			rampagingRhino = Instantiate (madRhinoPrefab) as Transform;
		} else {
			rampagingRhino = Instantiate (rampagingRhinoPrefab) as Transform;
		}
		rampagingRhino.position = rampagingRhinoPosition;
		rampagingRhino.rotation = rampagingRhinoRotation;
		Destroy(rampagingRhino.GetComponent<RampagingRhino>());
		rampagingRhinos.Add (rampagingRhinoID, rampagingRhino);
		rampagingTargets.Add (rampagingRhinoID, rampagingRhino.position);
	}

	public void KillRampagingRhino(int rampagingRhinoID) {
		if (rampagingRhinos.ContainsKey(rampagingRhinoID)) {
			Transform rampagingRhino = rampagingRhinos[rampagingRhinoID] as Transform;
			rampagingRhino.rigidbody.constraints = RigidbodyConstraints.None;
			ParticleSystem explosion = Instantiate (rhinoExplosionPrefab) as ParticleSystem;
			explosion.transform.position = rampagingRhino.position;
		}
	}

	public void DestroyRampagingRhino(int rampagingRhinoID) {
		if (rampagingRhinos.ContainsKey(rampagingRhinoID)) {
			Transform rampagingRhino = rampagingRhinos[rampagingRhinoID] as Transform;
			Destroy (rampagingRhino.gameObject);
			rampagingRhinos.Remove (rampagingRhinoID);
			rampagingTargets.Remove (rampagingRhinoID);
		}
	}
	
	public void UpdateRampagingRhino(int rampagingRhinoID, Vector3 rampagingRhinoPosition, Quaternion rampagingRhinoRotation) {
		if (rampagingRhinos.ContainsKey(rampagingRhinoID)) {
			Transform rampagingRhino = rampagingRhinos[rampagingRhinoID] as Transform;
			rampagingRhino.rotation = rampagingRhinoRotation;
			rampagingTargets[rampagingRhinoID] = rampagingRhinoPosition;
		}
	}

	public void UpdateScore(int score) {
		game.clientTreasureCountLabel.text = "Rhinos freed: " + score;
	}
}

