using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using com.deeperbeige.lib;

namespace com.deeperbeige.whiteout
{
		internal class Player : MonoBehaviour
		{
				public  int        playerID    { get; set; }

				public int score = 0;
				// life decreases when you fire
				// increases on fixed update
				public int life = 75;// , when you fire, this decreases, so you cannot fire again
				public int lifeDecrement = 75;
				public int maxLife = 300; // allows 3 shots in succession
				public int minLifeNeed = 75;

				// counter to delay between counts
				// else balls destroy players own balls
				// this decreases on the fixed update
				public int delayCounter = 0;
				public int maxDelay = 12;


				private Camera     playerCam;
				private GameObject launchpad;
				private GameObject ballHolder;
				private Color32    colour;
				private List<TouchTracker> touches;
				private const float swipeMultiplier = 0.5f;

				private class TouchTracker
				{
						public int     touchID;
						public Vector3 origin;
						public Vector3 destination;
						public float   startTime;
						public float   endTime;
				}

				private void Start ()
				{
						touches = new List<TouchTracker> ();

						ballHolder = GameObjects.FindAnywhere ("BallHolder");
						launchpad = GameObjects.FindNested (gameObject, "Launchpad");
						playerCam = GameObjects.FindNested (transform.parent, "Camera").GetComponent<Camera> ();

						launchpad.renderer.material.color = colour;
				}

				public void Init ()
				{
						switch (playerID) {
						case 1:
								colour = Colours.fromHex ("0x019EF5");
								break;
						case 2:
								colour = Colours.fromHex ((App.inst.players == 2) ? "0xFF3E75" : "0xFBB201");
								break;
						case 3:
								colour = Colours.fromHex ("0xFF3E75");
								break;
						case 4:
								colour = Colours.fromHex ("0x00DE87");
								break;
						}
				}
		
				private void Update ()
				{
						// Simple mouse-click for launch
						if (Application.isEditor && Input.GetMouseButtonDown (0)) {
								// Only clicks within this viewport
								Vector3 viewportPoint = playerCam.ScreenToViewportPoint (Input.mousePosition);
								if (viewportPoint.x >= 0 &&
										viewportPoint.x <= 1 &&
										viewportPoint.y >= 0 &&
										viewportPoint.y <= 1) {
										RaycastHit info;
										Ray ray = playerCam.ScreenPointToRay (Input.mousePosition);
										//Debug.DrawRay(ray.origin, ray.direction * 1000, Colours.fromRGB(255, 0, 0), 0.1f);
										if (launchpad.collider.Raycast (ray, out info, 20f)) {
												TouchTracker touchTracker = new TouchTracker ();
												touchTracker.touchID = -1;
												touchTracker.startTime = Time.time;
												touchTracker.origin = info.point;
												touchTracker.endTime = Time.time + 0.05f;
												touchTracker.destination = info.point + playerCam.transform.forward * 2;

												ProcessSwipe (touchTracker);
										}
								}
						}

						// Watch for new touches
						for (int j=0; j < Input.touchCount; j++) {
								Touch touch = Input.GetTouch (j);

								if (touch.phase == TouchPhase.Began) {
										// Only clicks within this viewport
										Vector3 viewportPoint = playerCam.ScreenToViewportPoint (touch.position);
										if (viewportPoint.x >= 0 &&
												viewportPoint.x <= 1 &&
												viewportPoint.y >= 0 &&
												viewportPoint.y <= 1) {
												RaycastHit info;
												Ray ray = playerCam.ScreenPointToRay (touch.position);
												//Debug.DrawRay(ray.origin, ray.direction * 1000, Colours.fromRGB(255, 0, 0), 0.1f);
												if (! launchpad.collider.Raycast (ray, out info, 20f))
														continue;

												TouchTracker touchTracker = new TouchTracker ();
												touchTracker.touchID = touch.fingerId;
												touchTracker.startTime = Time.time;
												touchTracker.origin = info.point;
												touchTracker.endTime = Time.time;
												touchTracker.destination = info.point;

												touches.Add (touchTracker);
										}
								}
						}

						// Process existing touches
						for (int j=0; j < touches.Count; j++) {
								TouchTracker touchTracker = touches [j];
								Touch touch = Input.GetTouch (touchTracker.touchID);

								if (touch.phase == TouchPhase.Ended) {
										ProcessSwipe (touchTracker);
										j--;
										continue;
								}

								RaycastHit info;
								Ray ray = playerCam.ScreenPointToRay (touch.position);
								//Debug.DrawRay(ray.origin, ray.direction * 1000, Colours.fromRGB(255, 0, 0), 0.1f);

								// Check we're still in the launchpad zone
								if (! launchpad.collider.Raycast (ray, out info, 20f)) {
										ProcessSwipe (touchTracker);
										j--;
										continue;
								}

								// Update swipe info
								touchTracker.destination = info.point;
								touchTracker.endTime = Time.time;
								//Debug.DrawRay(touchTracker.origin, touchTracker.destination - touchTracker.origin, Color.red, 0.1f);
						}
				}

				private void ProcessSwipe (TouchTracker swipe)
				{
						// Remove from list
						for (int j=0; j < touches.Count; j++) {
								if (touches [j] != swipe)
										continue;

								touches.RemoveAt (j);
								j--;
						}


						// Check time
						float swipeTime = swipe.endTime - swipe.startTime;
						if (swipeTime > 0.5f)
								return;

						// Check length
						Vector3 swipeDirection = swipe.destination - swipe.origin;
						if (swipeDirection.sqrMagnitude < 0.005f)
								return;
						//Debug.DrawRay(swipe.origin, swipe.destination - swipe.origin, Color.red, 3f);


						// check for life energy
						// This forces user to wait between swipes

						if (life < minLifeNeed) {
								return;
						}


					//	Debug.Log ("delay counter ENC " + delayCounter);
						// force a delay between swipes (if someone doing in quick successon
						if (delayCounter > 0) {
				Debug.Log ("delay counter forced return");
								return;
						}


						//life is decremented when swiped
						decrementLife ();
						// delay counter is set to 30,  when swiped to force delay
						delayCounter = maxDelay;
			Debug.Log ("delay counter set to max: " + delayCounter);

						// Launch a ball
						GameObject ballPath = Instantiate (Resources.Load ("BallPath")) as GameObject;
						ballPath.name = "ballPlayer" + playerID;
						ballPath.transform.parent = ballHolder.transform;
						ballPath.transform.localPosition = Vector3.zero;
						ballPath.GetComponent<BallPath> ().colour = colour;
						ballPath.GetComponent<BallPath> ().player = this;
						ballPath.GetComponent<BallPath> ().Init ();

						GameObject ball = GameObjects.FindNested (ballPath, "Ball");
						ball.transform.position = swipe.origin + Vector3.up * 0.55f;
						ball.rigidbody.AddForce (swipeMultiplier * swipeDirection / swipeTime, ForceMode.Impulse);
						ball.renderer.material.color = colour;
				}

				// method to increase the score.
				public void IncrementScore ()
				{
						score++;
			            
            GameObject scoreLabel = GameObjects.FindAnywhere ("Player" + playerID + "Score");

            if (null == scoreLabel)  {
                Debug.Log("Couldn't find scorelabel for player " + playerID);
             }  else {
                scoreLabel.GetComponent<UILabel> ().text = score.ToString ();
            }

						Debug.Log ("incremented score of player " + playerID + ", score: " + score);

				}

				public int GetScore ()
				{
						return score;
				}

				// method to decrease life
				public void decrementLife ()
				{
						Debug.Log ("LIfe is " + playerID + ", " + life);
						if (life > minLifeNeed) {
								life = life - lifeDecrement;
								Debug.Log ("decremented life of player " + playerID + ", life: " + life);
						}
				}
		
				public int GetLife ()
				{
						return life;
				}
				// 'Magic' function
				//to increase life over time.
				//increases delayCounter, so can only fire when delay counter is high enough
				private void FixedUpdate ()
				{
						if (life < maxLife) {
								life++;
						}

						if (delayCounter <= maxDelay
								&& delayCounter > 0) {
								delayCounter--;
						}
				}
		}
}


