using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using DDS.Stroke.Game;

namespace DDS.Stroke {
	
	public class GameController : MonoBehaviour {
		public Sprite[] StateLights;
		public float HoldTime = 3.0f;
		public float StaminaRefill = 0.05f;
		public float StaminaCost = 0.3f;
		public float StrokeForce = 5f;
		public bool DebugMode = false;

		private GameObject Player;
		private GameObject PlayerBoat;
		private GameObject StateLight;
		private GameObject DebugTextBlock;
		private GameObject uiCanvas;
		private GameObject CourseLine;
		private GameObject GoalMarker;
		private GameObject CourseComplete;
		private bool RaceComplete;
		private int ActionState = 0;
		private int StrokeCount;
		private int Min, Sec, DC;
		private float ActionHeldTime = 0;
		private float CurrentStamina = 1f;
		private float StrokeStrength;
		private string DebugBuffer;
		private string Timer;

		// Use this for pre-initialization
		void Awake ()
		{
			Player = GameObject.Find ("/Player");
			PlayerBoat = GameObject.Find ("/Player/Boat");
			uiCanvas = GameObject.Find ("/UI/Canvas");
			StateLight = GameObject.Find ("/UI/Canvas/StateLight");
			DebugTextBlock = GameObject.Find ("/UI/Canvas/DebugText");
			CourseLine = GameObject.Find ("/UI/Canvas/CourseLine");
			CourseComplete = GameObject.Find ("/UI/Canvas/CourseComplete");
			GoalMarker = GameObject.Find ("/GoalLine/GoalMarker");
			DebugTextBlock.gameObject.SetActive(DebugMode);
			StateLight.gameObject.SetActive (DebugMode);
		}

		// Use this for initizalization
		void Start ()
		{
			ActionState = 0;
			StateLight.GetComponent<Image> ().sprite = StateLights [ActionState];
			ActionHeldTime = 0;
			StrokeCount = 0;
			StrokeStrength = 0;
			RaceComplete = false;
		}

		// Use this to reset the current mode
		void Reset ()
		{
			
		}
	
		// Update is called once per frame
		void Update ()
		{
			CheckForFinish ();

			if (!RaceComplete)
			{
				// Regain Stamina and cap it if full
				CurrentStamina = Mathf.Clamp (CurrentStamina + StaminaRefill * Time.deltaTime, 0f, 1f);

				DetectActionKeyState (); //Poll InputManager for Keystate

				// If Action Key has been held for longer than held time, change to hold state
				if (ActionHeldTime > HoldTime) {
					ActionState = 2;
				}

				StateLight.GetComponent<Image> ().sprite = StateLights [ActionState];


				DC = DC + Convert.ToInt16 (Time.deltaTime * 100);
				SetTimer ();
			}

			if (Player.GetComponent<Player>().Surfing && !(ActionState == 2))
			{
				CurrentStamina = Mathf.Clamp (CurrentStamina - 0.1f * Time.deltaTime, 0f, 1f);
				Player.GetComponent<Rigidbody>().AddRelativeForce (Vector3.back * .01f);
			}

			if (DebugMode)
				UpdateDebugData ();
		}

		private void DetectActionKeyState ()
		{
			// On Frame Action Key is Pressed, Set Action State to Active
			if (Input.GetButtonDown ("ActionKey")) {
				ActionState = 1;
			}
			// If Action Key is still being held, and it is not the frame it was pressed in then Add time since last frame to the time it has been held
			if (Input.GetButton ("ActionKey") && !Input.GetButtonDown ("ActionKey")) {
				ActionHeldTime = ActionHeldTime + Time.deltaTime;
			}
			// When the Action key is released, return to base state, reset held time, and trigger any key actions
			if (Input.GetButtonUp ("ActionKey")) {
				ActionState = 0;
				ActionHeldTime = 0;
				Stroke ();
			}
			if (Input.GetButtonUp ("Cancel"))
				Application.Quit ();
			if (Input.GetButtonUp ("Submit"))
				SceneManager.LoadScene (SceneManager.GetActiveScene ().buildIndex);
		}

		private void Stroke ()
		{
			Player.GetComponent<AudioSource> ().Play();
			StrokeStrength = StrokeForce * CurrentStamina;
			Player.GetComponent<Rigidbody> ().AddRelativeForce (Vector3.forward * StrokeStrength);
			CurrentStamina = Mathf.Clamp(CurrentStamina - StaminaCost, 0f, 1f);
			StrokeCount++;
		}

		private void UpdateDebugData ()
		{
			DebugBuffer = null;
			DebugBuffer = "Current Force: " + Player.GetComponent<Rigidbody> ().GetRelativePointVelocity (Player.transform.position).z.ToString () + System.Environment.NewLine;
			DebugBuffer = DebugBuffer + "Current Location: " + Player.transform.position.z.ToString () + System.Environment.NewLine;
			DebugBuffer = DebugBuffer + "Current Drag: " + Player.GetComponent<Rigidbody> ().drag.ToString () + System.Environment.NewLine;
			DebugBuffer = DebugBuffer + "Current Stamina: " + CurrentStamina.ToString () + System.Environment.NewLine;
			DebugBuffer = DebugBuffer + "Current Time: " + Timer + System.Environment.NewLine;
			DebugBuffer = DebugBuffer + "Frame Time: " + Time.deltaTime.ToString () + System.Environment.NewLine;
			DebugBuffer = DebugBuffer + "Stroke Count: " + StrokeCount.ToString() + System.Environment.NewLine;
			DebugBuffer = DebugBuffer + "Last Stroke: " + StrokeStrength.ToString () + System.Environment.NewLine;
			DebugBuffer = DebugBuffer + "Race Complete: " + RaceComplete.ToString () + System.Environment.NewLine;
			DebugBuffer = DebugBuffer + "Canvas: " + uiCanvas.GetComponent<RectTransform> ().sizeDelta.x.ToString () + "X" + uiCanvas.GetComponent<RectTransform> ().sizeDelta.y.ToString ();
			DebugTextBlock.GetComponent<Text> ().text = DebugBuffer;
		}

		private void CheckForFinish ()
		{
			if (GoalMarker.GetComponent<Goal>().triggered) {
				RaceComplete = true;
				CourseComplete.gameObject.SetActive (true);
				CourseComplete.GetComponent<Text> ().text = "Course Complete" + System.Environment.NewLine + Timer;
			}
		}

		private void SetTimer()
		{
			Timer = null;
			if (DC >= 100) {
				Sec++;
				DC = DC - 100;
			}
			if (Sec >= 60) {
				Min++;
				Sec = Sec - 60;
			}
			if (Min < 10) {
				Timer = "0" + Min.ToString () + ":";
			} else {
				Timer = Min.ToString () + ":";
			}
			if (Sec < 10) {
				Timer = Timer + "0" + Sec.ToString () + ":";
			} else {
				Timer = Timer + Sec.ToString () + ":";
			}
			if (DC < 10) {
				Timer = Timer + "0" + DC.ToString ();
			} else {
				Timer = Timer + DC.ToString ();
			}
		}
	}
}