using UnityEngine;
using System.Collections;
#if !UNITY_5_0_0
using UnityEngine.SceneManagement;
#endif

public class Player : MonoBehaviour {

    // [SerializeField] Transform m_bulletFirePosition = null;
    // [SerializeField] GameObject m_bulletPrefab = null;
	[SerializeField] GameObject m_feet = null;
	[SerializeField] GameObject m_feetCrouch = null;
	[SerializeField] float m_feetHeightCrouching = 16;
	[SerializeField] float m_uncrouchTime = 0.5f;
	[SerializeField] AudioCue m_soundWin = null;
	[SerializeField] AudioCue m_soundLose = null;
	[SerializeField] AudioCue m_soundLotion = null;

    // Private variables 
    //--------------------------------

    CharacterMovement m_characterMovement = null;
    BodyBlockManager m_bodyBlockManager = null;

    // Public methods 
    //--------------------------------

    // Private methods 
    //--------------------------------

    bool m_crouching = false;
	bool m_shouldCrouch = false;
	float m_feetHeight = 0.0f;



    void Awake()
    {
        m_characterMovement = GetComponent<CharacterMovement>();
		m_bodyBlockManager = GetComponentInChildren<BodyBlockManager>();
    }

    void Update()
    {

		if ( Input.GetButtonDown("Crouch") )
		{
			m_shouldCrouch = !m_shouldCrouch;
		}

		bool feetHaveRoom = Physics2D.BoxCast( (Vector2)transform.position + new Vector2(0,-1), new Vector2(31,14), 0, Vector2.one, 0, LayerMask.GetMask("Ground")) == false;
		bool feetIntersecting = Physics2D.BoxCast( (Vector2)m_feet.transform.position + new Vector2(0,11), new Vector2(15,10), 0, Vector2.one, 0, LayerMask.GetMask("Ground"));

		// TODO: check if feet are through the floor
		if ( (m_shouldCrouch || feetIntersecting) && !m_crouching )
		{
			//
			// Player wants to crouch, or feet are intersecting the ground
			//

			m_crouching = true;
			m_feetCrouch.SetActive(true);
			m_feetHeight = m_feetHeightCrouching;
			m_feet.transform.localPosition = m_feet.transform.localPosition.WithY(m_feetHeight);
		}
		else if ( !m_shouldCrouch && m_crouching )
		{		
			//	
			// Player wants to stand
			//

			if ( feetHaveRoom || m_bodyBlockManager.GetHasStandingRoom() ) // NB: getHAsStanding room is expensive!
			{
				// Able to stand either the feet can decend, or the body can climb
				m_crouching = false;
				m_feetCrouch.SetActive(false);

				// TODO: stand slowly (move feet down over time so we don't penetrate collision)

				m_feetHeight = m_feetHeightCrouching;
				m_feet.transform.localPosition = m_feet.transform.localPosition.WithY(m_feetHeight);
			}
		}

		if ( m_crouching == false && m_feetHeight > 0 )
		{
			m_feetHeight = Mathf.MoveTowards(m_feetHeight,0, (Time.deltaTime*m_feetHeightCrouching)/m_uncrouchTime);
			m_feet.transform.localPosition = m_feet.transform.localPosition.WithY(m_feetHeight);
		}

		m_characterMovement.SetCrouching(m_crouching);

        if (m_dead || m_won)
        {
            m_characterMovement.SetWalkDirection(Vector3.zero);   
        }
        else
        {        	
            m_characterMovement.SetWalkDirection(new Vector3(Input.GetAxis("Horizontal"), 0.0f));

            if (Input.GetButtonDown("Jump"))
            {
                m_characterMovement.Jump();
            }
        }

		Animator animator = m_feet.GetComponent<Animator>();
		animator.SetBool("Walking", m_characterMovement.GetWalking() );
		animator.SetBool("Grounded",m_characterMovement.GetGrounded() );
		if ( m_characterMovement.GetWalking() )
			m_feet.transform.localScale = m_feet.transform.localScale.WithX(  Input.GetAxis("Horizontal") < 0 ? -1 : 1 ); 


    }

    void MsgDie()
    {
		if ( m_dead || m_won )
			return;
        
		m_dead = true;
    	StartCoroutine(CoroutineDie());
    }

    void MsgGoal( string nextLevel )
	{
		if ( m_dead || m_won )
			return;

        CarryTarget[] carryTargets = FindObjectsOfType<CarryTarget>();
        foreach (var eachCarryTarget in carryTargets)
        {
            if (!eachCarryTarget.IsFilled())
            {
                return;
            }
        }

		m_won = true;
		StartCoroutine(CoroutineWin(nextLevel));
    }

    void MsgPowerup()
    {
		SystemAudio.Play(m_soundLotion);
    	GetComponentInChildren<BodyBlockManager>().IncreaseMaxBlocks();
    }

    bool m_dead = false;
    bool m_won = false;

    IEnumerator CoroutineDie()
	{
		m_dead = true;
        yield return new WaitForSeconds(0.2f);

        HUD.Get.ShowDeathPopup();
        Camera.main.GetComponent<FollowCamera>().Shake(0.5f,10f);

		AudioSource audio = SystemAudio.Play(m_soundLose);

        yield return new WaitForSeconds(0.5f);

        HUD.Get.SetFade(true);

		// wait for dialog to finish
		while ( audio != null && audio.isPlaying )
			yield return new WaitForEndOfFrame();

    	// TODO: Death anim or something!
    	#if !UNITY_5_0_0
    	SceneManager.LoadScene(SceneManager.GetActiveScene().name);
    	#else
    		Application.LoadLevel(Application.loadedLevelName);
    	#endif
    }

	IEnumerator CoroutineWin(string nextLevel)
	{
		m_won = true;
        yield return new WaitForSeconds(0.2f);

		AudioSource audio = SystemAudio.Play(m_soundWin);

        yield return new WaitForSeconds(0.5f);

        HUD.Get.SetFade(true);

		// wait for dialog to finish
		while ( audio != null && audio.isPlaying )
			yield return new WaitForEndOfFrame();

    	// TODO: Death anim or something!
    	#if !UNITY_5_0_0
		SceneManager.LoadScene(nextLevel);
    	#else
		Application.LoadLevel(nextLevel);
    	#endif
    }
}
