using UnityEngine;
using System.Collections;
public class EnemyAI : MonoBehaviour
{
	#region Editor-type junk.
	public GameObject masterObject;
	public GameObject enemyMarker;
	private Transform mainCamera;
	public GameObject statusText;
	public AudioClip meleeSfx;
	public AudioClip technoWitchPowerupSfx;
	public Sprite normalSprite;
	public Sprite surrenderSprite;
	private PlayerControl pc;
	private EnemyGenerator enemyGenerator;
	#endregion
	#region Unit stats.
	public string unitName = "Enemy";
	public int currentHealth = 10;
	public int maxHealth = 10;
	public int currentActionPoints = 1;
	public int maxActionPoints = 1;
	public int damage = 4;
	public int bullhorned = 0;
	public int willStat = 20;
	public ProjectileBehavior.DamageType damageType = ProjectileBehavior.DamageType.Physical;	// BWAHAHAHAHAHAHAHAHA!
	public bool isFallingDown = false;
	public int xIndex;
	public int yIndex;
	private int willPowerUps = 0;
	private int apPowerUps = 0;
	private int damagePowerUps = 0;
	private bool isPoweringUp = true;//false;
	private bool hasAttackedPlayer = false;
	#endregion
	void Start ()
	{
		masterObject = GameObject.Find("_MasterObject");
		GameObject go = GameObject.Find("Main Camera");
		mainCamera = go.transform;
		pc = (GameObject.Find("_Player")).GetComponent<PlayerControl>();
		enemyGenerator = masterObject.GetComponent<EnemyGenerator>();
		enemyMarker.renderer.material.color = Color.red;
		if (unitName == "Techno Witch")
		{
			enemyMarker.renderer.material.color = Color.magenta;
		}
	}
	void Update ()
	{
		updateStatusText();
		if (!isFallingDown)
		{//isPoweringUp = true;
			if (unitName == "Techno Witch"	&&
				isPoweringUp)
			{//Debug.Log("<color=yellow>TECHNO WITCH SPINNING!</color>");
				transform.Rotate(Vector3.up * Time.deltaTime * 4000.0f);
				return;
			}
			float speed = 3.0f;
			float step = speed * Time.deltaTime;
			Vector3 targetDir = mainCamera.position - transform.position;
			Vector3 newDir = Vector3.RotateTowards(transform.forward, targetDir, step, 0.0f);
			transform.rotation = Quaternion.LookRotation(newDir);
		}
		else
		{
			float speed = 5.0f;
			float step = speed * Time.deltaTime;
			Vector3 targetDir = transform.position - mainCamera.position;
			Vector3 newDir = Vector3.RotateTowards(transform.forward, targetDir, step, 0.0f);
			transform.rotation = Quaternion.LookRotation(newDir);
			transform.position = Vector3.Lerp(gameObject.transform.position, gameObject.transform.position + new Vector3(0.0f, -0.16f, 0.0f), step / 2.0f);
		}
	}
	// NOTE: This will trigger AFTER the enemy acts and bullhorned is decremented!
	//		 This is both advantageous and... less so in the game systems.
	//		 Main problem is it's probably not intuitively clear because this is
	//		 a turn-based game...
	public void OnTriggerEnter (Collider projectile)
	{
		ProjectileBehavior pb = projectile.GetComponent<ProjectileBehavior>();
		if (pb != null)
		{
			if (!pc.isPenetratingShot)
			{
				Destroy(projectile.gameObject);
			}
			else
			{
				pc.audio.PlayOneShot(pc.getRandomBulletImpactSfx());
			}
			if (currentHealth <= 0)	// Already dead - don't let multiple projectiles trigger rest of code!
			{
				return;
			}
			currentHealth -= pc.damage;		// Should this be a player property or a projectile property?
			if (currentHealth <= 0)
			{
				if (bullhorned > 0	&&
					!hasAttackedPlayer)
				{
					pc.setLastLogMessage("Perps gain Will from your execution of one of their own!");
					enemyGenerator.boostEnemyWill();
				}
				if (bullhorned > 0	&&
					hasAttackedPlayer)
				{
					pc.setLastLogMessage("Sentence carried out - ammo refilled!");
					pc.refillAmmo();
				}
				pc.grantKill(unitName);
				isFallingDown = true;
				(masterObject.GetComponent<EnemyGenerator>()).enemyList.Remove(this.gameObject);
				Destroy(gameObject, 0.3f);
			}
		}
	}
	public void setTilePosition (int xIndex, int yIndex)
	{
		this.xIndex = xIndex;
		this.yIndex = yIndex;
		this.gameObject.transform.position = new Vector3(this.xIndex * DungeonGenerator.tileSize, 0.0f, this.yIndex * DungeonGenerator.tileSize);
	}
	/*
	NOTE: Action Point system has player priority action. Enemies with greater or equal action points then act.
		  All units (player and enemies) should reach 0 AP at the same time and then AP is reset to max AP per each unit.
		  //-------------------------------------------------------------//
			Example:
				1) Player has 2 AP, Enemy A has 1 AP, Enemy B has 2 AP.
				2) Player moves. Enemy A does not move. Enemy B moves.
				3) Player has 1 AP, Enemy A has 1 AP, Enemy B has 2 AP.
				4) Player moves. Enemy A moves. Enemy B moves.
				5) Player has 0 AP. Enemy A has 0 AP. Enemy B has 0 AP.
				6) AP is reset (to max, so go to 1).
		  //-------------------------------------------------------------//
	*/
	public void takeTurn ()
	{
		//for (int i = 0; i < currentActionPoints; i++)		// Crap was when we had a turn-by-turn with rigid AP for all units.
		//{													// Retain in case this new-fangled shit turns sour.
			if (bullhorned > 0)
			{
				bullhorned--;
				if (bullhorned <= 0)
				{
					bullhorned = 0;
					this.GetComponent<SpriteRenderer>().sprite = normalSprite;
				}
			}
			else
			{
				if (unitName == "Techno Witch")
				{
					// Allow Techno Witch to buff with one of:
					// 1) Will increase by 100 to completely negate Bullhorns.
					// 2) Increase AP by 1. Partly negates player Sprint.		Stacks.
					// 3) Increase melee damage by 1.							Stacks.
					int powerRoll = Random.Range(0, 6);
					switch (powerRoll)
					{
						case 0:
							willStat += 10;
							willPowerUps++;
							break;
						case 1:
							currentActionPoints += 1;
							apPowerUps++;
							break;
						case 2:
							damage += 1;
							damagePowerUps++;
							break;
					}
					if (powerRoll <= 2)
					{//Debug.Log("<color=magenta>TECHNO WITCH POWERUP!</color>");
						// Visual and sound effects!
						setToPoweringUp();
						Invoke("setToNotPoweringUp", 0.5f);
						return;	// Only one action per AP!
					}
				}
				int xDst = xIndex;
				int yDst = yIndex;
				float distance = 0.0f;
				float currentDistance = Vector2.Distance(new Vector2(pc.xIndex, pc.yIndex), new Vector2(xIndex, yIndex));
				// North.
				if (yIndex - 1 > 0	&&
					DungeonGenerator.mazeRoom[xIndex, yIndex - 1] == (int)DungeonGenerator.TileType.Floor)
				{
					distance = Vector2.Distance(new Vector2(pc.xIndex, pc.yIndex), new Vector2(xIndex, yIndex - 1));
					if (distance < currentDistance)
					{
						xDst = xIndex;
						yDst = yIndex - 1;
					}
				}
				// South.
				if (yIndex + 1 < DungeonGenerator.maxDimension - 1	&&
					DungeonGenerator.mazeRoom[xIndex, yIndex + 1] == (int)DungeonGenerator.TileType.Floor)
				{
					distance = Vector2.Distance(new Vector2(pc.xIndex, pc.yIndex), new Vector2(xIndex, yIndex + 1));
					if (distance < currentDistance)
					{
						xDst = xIndex;
						yDst = yIndex + 1;
					}
				}
				// East.
				if (xIndex - 1 > 0	&&
					DungeonGenerator.mazeRoom[xIndex - 1, yIndex] == (int)DungeonGenerator.TileType.Floor)
				{
					distance = Vector2.Distance(new Vector2(pc.xIndex, pc.yIndex), new Vector2(xIndex - 1, yIndex));
					if (distance < currentDistance)
					{
						xDst = xIndex - 1;
						yDst = yIndex;
					}
				}
				// West.
				if (xIndex + 1 < DungeonGenerator.maxDimension - 1	&&
					DungeonGenerator.mazeRoom[xIndex + 1, yIndex] == (int)DungeonGenerator.TileType.Floor)
				{
					distance = Vector2.Distance(new Vector2(pc.xIndex, pc.yIndex), new Vector2(xIndex + 1, yIndex));
					if (distance < currentDistance)
					{
						xDst = xIndex + 1;
						yDst = yIndex;
					}
				}
				// Got a possible position - check for other units!
				if (enemyGenerator.isTileClearOfUnits(xDst, yDst))
				{
					if (xDst == pc.xIndex	&&
						yDst == pc.yIndex)
					{
						hasAttackedPlayer = true;
						pc.takeDamage(damage, damageType, unitName == "Thief");
						audio.PlayOneShot(meleeSfx);
					}
					else
					{
						setTilePosition(xDst, yDst);
					}
				}
			}
		//}
		//currentActionPoints = maxActionPoints;
	}
	public void updateStatusText ()
	{
		TextMesh tm = statusText.GetComponent<TextMesh>();
		tm.text = "";
		if (bullhorned > 0)
		{
			string turnString = bullhorned == 2 ? "turn" : "turns";	// CAN'T NOT DO THIS.
			if (unitName == "Techno Witch")
			{
				tm.text += "Stunned for " + (bullhorned - 1) + " " + turnString + "\n" + "Can't arrest Techno Witch!";
			}
			else
			{
				tm.text += "Surrendering for " + (bullhorned - 1) + " " + turnString + "\n" + "Arresting perps restores health.";
			}
		}
		if (hasAttackedPlayer)
		{
			tm.text += "\n\n" + "Assault: Sentence is death.\nBullhorn + kill to confiscate ammo.";
		}
		if (unitName == "Techno Witch")
		{
			tm.text += "\n" + "Techno Witch Powerups:"		+
					   "\n+" + willPowerUps * 10 + " Will"	+
					   "\n+" + apPowerUps + " AP"			+
					   "\n+" + damagePowerUps + " Damage";
		}
		if (tm.text != "")
		{
			statusText.transform.position = new Vector3(xIndex * DungeonGenerator.tileSize, 0.08f, yIndex * DungeonGenerator.tileSize);
			statusText.transform.Translate(statusText.transform.forward * -0.1f);
			float speed = 5.0f;
			float step = speed * Time.deltaTime;
			Vector3 targetDir = statusText.transform.position - mainCamera.position;
			Vector3 newDir = Vector3.RotateTowards(statusText.transform.forward, targetDir, step, 0.0f);
			float angle = Quaternion.Angle(statusText.transform.rotation, Quaternion.LookRotation(newDir));
			if (angle != 180.0f)	// Argh - reversed!
			{
				statusText.transform.rotation = Quaternion.LookRotation(newDir);
			}
			// When the player faces North (statusText facing South) the enemy sprite hides the text!
			// TRANSLATE FORWARD BORKED IN THAT ORIENTATION. NO TIME TO FIGURE OUT WHY. PATCH IT.
			if (pc.playerFacing == PlayerControl.Direction.North)
			{
				statusText.transform.Translate(statusText.transform.forward * 0.2f);
			}
		}
	}
	public bool isWillRollSucceed ()
	{
		if (Random.Range(1, 101) > willStat)
		{
			return true;
		}
		return false;
	}
	public bool isBullhornSubmit (int voiceStat)
	{
		if (isWillRollSucceed())
		{
			bullhorned += Random.Range(3, 4 + voiceStat);	// Bullhorns stack!
			SpriteRenderer sr = this.GetComponent<SpriteRenderer>();
			sr.sprite = surrenderSprite;
		}
		if (bullhorned > 0)
		{
			return true;
		}
		return false;
	}
	private void setToPoweringUp ()
	{
		this.isPoweringUp = true;
		pc.audio.PlayOneShot(technoWitchPowerupSfx);
	}
	private void setToNotPoweringUp ()
	{
		this.isPoweringUp = false;
	}
}