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

public class PlayerMovement : MonoBehaviour {

	//Movement
	float layerWidth = 4.2f;
	float moveSpeed = 0.05f;
	float localX = 0;
	bool moving = false;
	float localZ = 0;

	//Depth
	GameObject scripts;
	Dictionary<string, GameObject> layers = new Dictionary<string, GameObject>();
	string layerName = "red";

	//Shooting
	public GameObject bullet;
	bool bulletExists = false;
	bool triggerHeld = false;
	Vector3 bulletRotation;
	float rotateAmount;
	string animTrigger = "back";

	//Teleporting
	public GameObject teleportSprite;
	bool invincible = false;
	int invincibleTimerMax = 15;
	int invincibleTimer = 0;

	//Sounds
	AudioSource shootSound;
	AudioSource teleportSound;

	// Use this for initialization
	void Start () {
		//Find game objects
		scripts = GameObject.Find("ScriptContainer");
		layers.Add ("red", GameObject.Find ("RedLayer"));
		layers.Add ("blue", GameObject.Find ("BlueLayer"));
    	layers.Add ("green", GameObject.Find ("GreenLayer"));
   		layers.Add ("yellow", GameObject.Find ("YellowLayer"));

		//Get the sounds
		shootSound = GetComponents<AudioSource>()[0];
		teleportSound = GetComponents<AudioSource>()[1];

		//Start invincible
		invincible = true;
		invincibleTimer = invincibleTimerMax;
	}
	
	// Update is called once per frame
	void Update () {
		//Move player on plane
		localX += Input.GetAxis("Horizontal") * moveSpeed;
		localZ += Input.GetAxis("Vertical") * moveSpeed;
		if(Input.GetAxis("Horizontal") != 0 || Input.GetAxis("Vertical") != 0){
			moving = true;
		}
		else{
			moving = false;
		}

		if(localX < -layerWidth)
			localX = -layerWidth;
		else if(localX > layerWidth)
			localX = layerWidth;
		if(localZ< -layerWidth)
			localZ = -layerWidth;
		if(localZ > layerWidth)
			localZ = layerWidth;

		//Move based on the layer's position and local position
		transform.position = new Vector3(layers[layerName].transform.position.x + localX,
		                                 layers[layerName].transform.position.y,
		                                 layers[layerName].transform.position.z + localZ);

		//Aim
		rotateAmount = Mathf.Atan2 (Input.GetAxis("AimHorizontal"), Input.GetAxis("AimVertical")) * Mathf.Rad2Deg;
		bulletRotation = new Vector3(90, rotateAmount, 0);

		//Animate the rotation
		if(rotateAmount < 0){
			rotateAmount += 360;//Fix the angle when it wraps
		}
		if(rotateAmount >= 22.5 && rotateAmount < 67.5){
			animTrigger = "backright";
		}
		else if(rotateAmount >= 67.5 && rotateAmount < 112.5){
			animTrigger = "right";
		}
		else if(rotateAmount >= 112.5 && rotateAmount < 157.5){
			animTrigger = "frontright";
		}
		else if(rotateAmount >= 157.5 && rotateAmount < 202.5){
			animTrigger = "front";
		}
		else if(rotateAmount >= 202.5 && rotateAmount < 247.5){
			animTrigger = "frontleft";
		}
		else if(rotateAmount >= 247.5 && rotateAmount < 292.5){
			animTrigger = "left";
		}
		else if(rotateAmount >= 292.5 && rotateAmount < 337.5){
			animTrigger = "backleft";
		}
		else if(rotateAmount >= 337.5 || rotateAmount < 22.5){
			animTrigger = "back";
		}
		if(!GetComponent<Animator>().GetCurrentAnimatorStateInfo(0).IsName(animTrigger) || !moving){
			GetComponent<Animator>().SetTrigger(animTrigger);
		}

		//Shoot
		if(Input.GetAxis ("Shoot") > .2){
			if(!triggerHeld){
				shoot();
				triggerHeld = true;
			}
		}
		else{
			triggerHeld = false;
		}

		//Handle invinciblity
		if(invincible){
			invincibleTimer --;
			if(invincibleTimer <= 0){
				invincible = false;
			}
		}

	}

	void OnCollisionEnter(Collision collision){
		if(collision.gameObject.tag == "Enemy"){
			if(collision.gameObject.GetComponent<Enemy>().layerName == layerName){
				//If I am invincible, kill the enemy.
				if(invincible){
					collision.gameObject.GetComponent<Enemy>().killMe(true);
				}
				//Otherwise, take damage.
				else{
					scripts.GetComponent<GameManager>().loseHealth(collision.gameObject.GetComponent<Enemy>().damageAmount);
					collision.gameObject.GetComponent<Enemy>().killMe(false);
				}
			}
		}
	}

	void shoot(){
		if(!bulletExists){
			bulletExists = true;
			bullet.transform.eulerAngles = bulletRotation;
			bullet.GetComponent<Bullet>().localX = localX;
			bullet.GetComponent<Bullet>().localZ = localZ;
			Instantiate(bullet);

			shootSound.Play();
		}
	}

	public void teleportTo(Vector3 newSpot, string layerName){

		//Display the teleport sprite
		teleportSprite.transform.position = transform.position;
		Instantiate(teleportSprite);

		this.layerName = layerName;
		localX = newSpot.x - layers[layerName].transform.position.x;
		localZ = newSpot.z - layers[layerName].transform.position.z;

		//Make me invincible
		invincible = true;
		invincibleTimer = invincibleTimerMax;

		teleportSound.Play();
	}

	public void setBulletExists(bool bulletExists){
		this.bulletExists = bulletExists;
	}

	public float getLocalX(){
		return localX;
	}

	public float getLocalZ(){
		return localZ;
	}

	public string getLayerName(){
		return layerName;
	}

	public float getRotateAmount(){
		return rotateAmount;
	}

	public string getAnimTrigger(){
		return animTrigger;
	}

	public bool isMoving(){
		return moving;
	}
}
