using UnityEngine;
using System.Collections;

public class GunSubController : MonoBehaviour {

	public Gun gunInfo;
	public Gun secondaryInfo;

	public Transform gun;
	public Transform ReloadBar;
    public float GunAngleOffset=0;

	public Vector2 AimPoint { get; set; }
	public Transform firePoint { get; set; }
	public bool Disabled { get; set; }

	private enum WState
	{
		Sprinting,
		Marathon,
		Ready,
		FiringPrimary,
		FiringSecondary,
		Recoil,
		Reload,
		Switch
	}
	private WState state;
	private float lastStateChangeTime;
	private float lastSprintingTime;
	private float startRecoilTime;
	private float startReloadTime;

	private bool triggerQueued;
	private bool secondaryTriggerQueued;
	private bool reloadQueued;
	private GameObject cameraGO;
	
	private GameController gc;
	private AudioSource asrc;
	private AudioClip aclip;

    private Vector3 origScale;
    private Vector3 flipScale;
	
	// Use this for initialization
	void Start () {
		GameObject go = GameObject.Find ("GameController");
		gc = go.GetComponent<GameController>();

		cameraGO = GameObject.Find ("Main Camera");
		firePoint = gun.Find("FirePoint");

        origScale = gun.localScale;
        flipScale = new Vector3(-origScale.x, origScale.y, origScale.z);

		/*
		if(transform == gc.Player)
		{
			asrc = gc.PlayerAudio;
			aclip = gc.GunshotPlayerClip;
		}
		else
		{
			asrc = gc.EnemyAudio;
			aclip = gc.GunshotEnemyClip;
		}
		*/

		Disabled = false;

	
		if(ReloadBar != null)
			ReloadBar.GetComponent<Renderer>().enabled = false;

		ReloadSecondary();
		EnterState(WState.Ready);
	}

	public void HandleSwitch()
	{
		firePoint = gun.Find("FirePoint");
		gunInfo.Reload();
	}
	

	void FixedUpdate () {
		ShowReloadBar();

		if(Disabled)
		{
			gun.transform.localPosition = new Vector3(0, -0.1f, 0);
			triggerQueued = false;
			secondaryTriggerQueued = false;
			return;
		}
		else
		{
			gun.transform.localPosition = new Vector3(0, 0.03f, 0);
		}

		FaceGunToAim();

		FUpdateGun();

	}

	private void FUpdateGun()
	{
		if(AimPoint.x > transform.position.x)
			gun.localScale = flipScale;
		else
			gun.localScale = origScale;

		// CHECK TRIGGERS TO EXIT STATE
		switch(state)
		{
		case WState.Ready:
			if(gunInfo.isEmpty() || reloadQueued)
				EnterState (WState.Reload);
			else if(triggerQueued)
				EnterState (WState.FiringPrimary);
			else if(secondaryTriggerQueued)
			{
				if(secondaryInfo.loadedAmmo > 0)
					EnterState (WState.FiringSecondary);
				else
					secondaryTriggerQueued = false;
			}
			break;
		case WState.Recoil:
			if(Time.time - startRecoilTime > gunInfo.RefireDelay)
				EnterState (WState.Ready);
			break;
		case WState.Reload:
			if(secondaryTriggerQueued && secondaryInfo.loadedAmmo > 0)
			{
				EnterState (WState.FiringSecondary);
			}
			else if(triggerQueued && !gunInfo.isEmpty())  // cancel reload to fire
			{
				EnterState(WState.FiringPrimary);
				reloadQueued = false;
			}
			else if(Time.time - startReloadTime > gunInfo.ReloadTime)
			{
				//gc.PlaySound(currentWeapon.ReloadSoundEnd, 1.0f);
				gunInfo.Reload();
				EnterState(WState.Ready);
				reloadQueued = false;
			}
			break;
		}
	}

	private void EnterState(WState newState)
	{
		//Debug.Log("GunSubController entering state " + newState + " at time " + Time.time);
		
		WState oldState = state;
		state = newState;
		
		switch(newState)
		{
		case WState.FiringPrimary:
			FireWeapon();
			EnterState(WState.Recoil);
			break;
		case WState.FiringSecondary:
			FireSecondary();
			EnterState(WState.Recoil);
			break;

		case WState.Recoil:
			startRecoilTime = Time.time;
			break;
		case WState.Reload:
			//Debug.Log (transform.name + " is reloading");
			//gc.PlaySound(currentWeapon.ReloadSoundStart, 1.0f);
			startReloadTime = Time.time;
			triggerQueued = false;
			secondaryTriggerQueued = false;
			break;
		}
		
	}

	public void PullTrigger()
	{
		if(!Disabled && state == WState.Ready)
			triggerQueued = true;
	}

	public void PullSecondaryTrigger()
	{
		if(!Disabled && (state == WState.Ready || state == WState.Reload))
			secondaryTriggerQueued = true;
	}

	private void FaceGunToAim()
	{
		if(gun == null)
			return;
		
		float dx = AimPoint.x - gun.position.x;
		float dy = AimPoint.y - gun.position.y;
		float aimangle = Mathf.RoundToInt(Mathf.Atan2(dx, dy) * -180/Mathf.PI) - GunAngleOffset;
		
		gun.eulerAngles = new Vector3(0,0,aimangle);
	}

	public void FireWeapon()
	{
		DoFire(gunInfo);
	}

	public void FireSecondary()
	{
		DoFire(secondaryInfo);
	}

	public void ReloadSecondary()
	{
		secondaryInfo.Reload();
	}

	private void DoFire(Gun gun)
	{
		if(gun.Projectile == null)
		{
			return;
		}

		//Debug.Log ("Weapon Fired by " + transform.name);
		//iTween.Stab(gameObject, iTween.Hash ("audiosource", asrc, "audioclip", aclip, "volume", gc.Volume));

		gun.loadedAmmo--;
		if(!gun.Automatic)
		{
			triggerQueued = false;
			secondaryTriggerQueued = false;
		}
		
		Transform projObj = (Transform) GameObject.Instantiate(gun.Projectile);
		DestroyTimer dt = projObj.GetComponent<DestroyTimer>();
		if(dt!=null  && gun.Range != 0)  // Range zero uses default on projectile prefab
			dt.Countdown = gun.Range / gun.MuzzleSpeed; 

		Vector2 facing = AimPoint - new Vector2(firePoint.position.x, firePoint.position.y);
		Vector2 targetVel = facing.normalized * gun.MuzzleSpeed;
		// TODO add inherited velocity to projectile, factor: ed write as prop in gun, read in DoFire

		projObj.position = firePoint.position;
		projObj.eulerAngles = firePoint.eulerAngles;
		if(projObj.GetComponent<Rigidbody2D>() != null)
			projObj.GetComponent<Rigidbody2D>().AddForce(targetVel * projObj.GetComponent<Rigidbody2D>().mass / Time.fixedDeltaTime);

		if(gun.MuzzleFlashPrefab != null)
		{
			Transform flashObj = (Transform) GameObject.Instantiate(gun.MuzzleFlashPrefab);
			flashObj.position = firePoint.position;
			flashObj.eulerAngles = firePoint.eulerAngles;
		}

		Vector3 amt = (transform.position - (Vector3)AimPoint).normalized * gun.Kickback;
		iTween.MoveBy(gameObject, iTween.Hash("amount",amt,"time",gun.Kicktime,"easetype",iTween.EaseType.easeOutBack));				

	}

	private void ShowReloadBar()
	{
		if(ReloadBar == null)
			return;

		if(Disabled || state != WState.Reload || gunInfo.ReloadTime < 0.2f)
		{
			ReloadBar.GetComponent<Renderer>().enabled = false;
			return;
		}

		float scale = gunInfo.ReloadTime - (Time.time - startReloadTime);
		ReloadBar.localScale = new Vector3(scale, 0.5f, 1);
		ReloadBar.GetComponent<Renderer>().enabled = true;
	}

}
