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

//enum for wave firing states
public enum FireState{
	Idle,
	Charging,
	Fire,
	CoolDown
};
	
/* This is the script for the player
 */
public class Player : MonoBehaviour {

	private Vector3 playerRotationAngle; //player rotation
	private Vector3 waveShotRotation; //wave shot rotation, Eular Angle
	private FireState playerFireState;
	private int chargeLevel;
	private float elaspedChargeTime;
	private float coolDownTimer;
	private Vector3[] spawnLocations;
	private float[] reboundLocations;
	private int velocityMulitplier;
	private AudioSource chargeLevelAPly;
	private AudioSource chargingAPly;
	private AudioSource turnAPly;
	private AudioSource damageAPly;

	private Renderer chargeRender;

	public Direction playerDirection = Direction.Up; //direction the player is facing
	public GameObject waveShot; //wave prefab
	//public GUITexture chargeGUI; //charge indictator

	//Audio sources
	public GameObject chargeLevelAdS;
	public GameObject chargingAds;
	public GameObject turnAds;
	public GameObject damageAds;

	//wave spawn points for player
	public GameObject[] spawnPoints;

	//rebound points for waves; place enemy spawns here
	public GameObject[] reboundPoints;

	public float playerWaveVelocity; //speed of player waves
	public float chargeLevelTime; //charge time
	public float coolDown; //cool down time
	public int health;
	public bool dead; //is the player dead
	//public GameObject uiText; //UI Text


	//public Quaternion waveShotRotation;

	// Use this for initialization
	void Start () {
		elaspedChargeTime = 0;
		coolDownTimer = coolDown;
		chargeLevel = 1;
		chargeRender = this.gameObject.GetComponent<Renderer> ();
		SetChargeTexture();

		spawnLocations = new Vector3[4];
		spawnLocations [0] = spawnPoints[0].transform.position;
		spawnLocations [1] = spawnPoints[1].transform.position;
		spawnLocations [2] = spawnPoints[2].transform.position;
		spawnLocations [3] = spawnPoints[3].transform.position;

		reboundLocations = new float[4];
		reboundLocations[0] = reboundPoints[0].transform.position.x;
		reboundLocations[1] = reboundPoints[1].transform.position.x;
		reboundLocations[2] = reboundPoints[2].transform.position.z;
		reboundLocations[3] = reboundPoints[3].transform.position.z;

		chargeLevelAPly = chargeLevelAdS.GetComponent<AudioSource> ();
		chargingAPly = chargingAds.GetComponent<AudioSource> ();
		turnAPly = turnAds.GetComponent<AudioSource> ();
		damageAPly = damageAds.GetComponent<AudioSource> ();

		/*
		spawnLocations [0] = spawnPoint_Up.transform.position;
		spawnLocations [1] = spawnPoint_Down.transform.position;
		spawnLocations [2] = spawnPoint_Left.transform.position;
		spawnLocations [3] = spawnPoint_Right.transform.position;
		*/
		playerRotationAngle = transform.rotation.eulerAngles;
		waveShotRotation = waveShot.transform.rotation.eulerAngles;
		playerFireState = FireState.Idle;
		dead = false;
		velocityMulitplier = 1;
	}
	
	// Update is called once per frame
	void Update () {
		HandleKeyboardInput();
		switch (playerFireState) {
		case FireState.Idle:
			break;

		case FireState.Charging:
			ChargeWave (Time.deltaTime * 100);
			break;

		case FireState.Fire:
			FireWave ();
			break;

		case FireState.CoolDown:
			coolDownTimer -= (Time.deltaTime * 100);
			if (coolDownTimer <= 0) {
				coolDownTimer = coolDown;
				playerFireState = FireState.Idle;
			}
			break;
		}
		SetChargeTexture();
		//UpdateUIText ();

	}

	public int Health{
		get{return health; }
	}

	/*
	private void UpdateUIText(){
		uiText.GetComponent<Text> ().text = "Health : " + health;
	}
	*/


	/*handler for input
	*/
	private void HandleKeyboardInput()
	{
		//check what directional key was pressed
		//update rotaion and shot direction with input
		if(Input.GetKeyDown(KeyCode.UpArrow))
		{
			playerRotationAngle.y = (-90);
			waveShotRotation.z = (0);
			playerDirection = Direction.Up;
			velocityMulitplier = 1;
			turnAPly.Play ();
		}

		else if(Input.GetKeyDown(KeyCode.DownArrow))
		{
			playerRotationAngle.y = (90);
			waveShotRotation.z = (180);
			playerDirection = Direction.Down;
			velocityMulitplier = 1;
			turnAPly.Play ();
		}

		else if(Input.GetKeyDown(KeyCode.LeftArrow))
		{
			playerRotationAngle.y = (180);
			waveShotRotation.z = (90);
			playerDirection = Direction.Left;
			velocityMulitplier = 2;
			turnAPly.Play ();
		}

		else if(Input.GetKeyDown(KeyCode.RightArrow))
		{
			playerRotationAngle.y = (0);
			waveShotRotation.z = (-90);
			playerDirection = Direction.Right;
			velocityMulitplier = 2;
			turnAPly.Play ();
		}


		//change player direction
		transform.rotation = Quaternion.Euler (playerRotationAngle);

		//check for firing input (spacebar)
		//first check if the player is Charging
		if (playerFireState == FireState.Charging) {
			//if yes, check if they have stopped Charging
			if (Input.GetKeyUp (KeyCode.Space)) {
				playerFireState = FireState.Fire;
				chargingAPly.Stop ();
			}
		}
		//check if the player is starting a charge
		else if (playerFireState == FireState.Idle) {
			if (Input.GetKey (KeyCode.Space)) {
				playerFireState = FireState.Charging;
				ChargeWave (Time.deltaTime * 100);
				chargingAPly.Play ();
			}
		}
	}

	//charges wave
	private void ChargeWave(float t){
		elaspedChargeTime += t;
		//only update charge level if not at max
		if (chargeLevel < 4) {
			if ((elaspedChargeTime - ((chargeLevel-1) * chargeLevelTime)) >= chargeLevelTime) {
				chargeLevel += 1;
				chargeLevelAPly.clip = GameController.waveChargeAudio[chargeLevel-2];
				chargeLevelAPly.Play ();
			}
		}
	}

	//Fires wave
	private void FireWave(){
		Wave.CreateNewWave ((GameObject)Instantiate (waveShot, GetSpawnLocation(), Quaternion.Euler(waveShotRotation)), WaveType.Player, chargeLevel, playerDirection,
			playerWaveVelocity * velocityMulitplier, GetReboundLocation());
		elaspedChargeTime = 0;
		chargeLevel = 1;
		playerFireState = FireState.CoolDown;
	}

	//create vector3 for wave starting position
	private Vector3 GetSpawnLocation(){
		Vector3 position = Vector3.zero;
		switch (playerDirection) {
		case Direction.Up:
				position = spawnLocations [0];
				break;

			case Direction.Down:
			position = spawnLocations [1];
				break;

			case Direction.Left:
			position = spawnLocations [2];
				break;

			case Direction.Right:
			position = spawnLocations [3];
				break;
		}
		return position;
	}

	private float GetReboundLocation(){
		float position = 10.0f;
		switch (playerDirection) {
		case Direction.Up:
			position = reboundLocations [0];
			break;

		case Direction.Down:
			position = reboundLocations [1];
			break;

		case Direction.Left:
			position = reboundLocations [2];
			break;

		case Direction.Right:
			position = reboundLocations [3];
			break;
		}
		return position;
	}

	//updates the charge indictator
	private void SetChargeTexture(){
		if (playerFireState == FireState.CoolDown) {
			chargeRender.material.mainTexture= GameController.chargeTex [0];
		} 
		else {
			chargeRender.material.mainTexture= GameController.chargeTex [chargeLevel];
			}
		chargeRender.material.shader = Shader.Find ("Sprites/Default");
	}

	void OnTriggerEnter(Collider other){
		if (other.gameObject.tag == "WaveEnemy") {
			LoseHealth(other.gameObject.GetComponent<Wave>().Level);
			Destroy(other.gameObject);
		}
	}

	//TODO; when new game implemented, reset audio clip
	private void LoseHealth(int damage){
		health -= damage;
		if (health < 1) {
			health = 0;
			damageAPly.clip = GameController.gameOverAudio;
			damageAPly.Play ();
			this.gameObject.SetActive (false);

		} 
		else {
			damageAPly.Play ();
		}
	}

}
