using UnityEngine;
using System.Collections;

public class CharacterMovement : MonoBehaviour {

    // Exposed variables 
    //--------------------------------

    [SerializeField] float m_speed = 20.0f;
    [SerializeField] float m_jumpForce = 50.0f;
    [SerializeField] bool m_faceWalkingDirection = false;

    [SerializeField] float m_groundDetectDistance = 10.0f;
    [SerializeField] Vector2 m_groundBoxDetectSize = new Vector2(10.0f, 10.0f);

    [SerializeField] float m_earlyJumpToleranceTime = 0.1f;
    [SerializeField] float m_lateJumpToleranceTime = 0.1f;

	[SerializeField] AudioCue m_soundJump = null;
	[SerializeField] AudioCue m_soundLand = null;
	[SerializeField] AudioCue m_soundWalk = null;

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

    bool m_grounded = true;
    Rigidbody2D m_rigidBody = null;
    float m_earlyJumpTimer = 0.0f;
	float m_lateJumpTimer = 0.0f;
    AudioSource m_soundWalkSource = null;
	bool m_walking = false;
    bool m_crouching = false;

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

    public void SetWalkSpeed(float speed)
    {
        m_speed = speed;
    }

    public void SetCrouching(bool crouching)
    {
		m_crouching = crouching;
    }

	public bool GetWalking() { return m_walking; }
	public bool GetGrounded() { return m_grounded; }
    public bool GetShouldAnimateLegs() { return m_walking && m_grounded; }

    public void SetWalkDirection(Vector3 walkDirection)
    {
		if ( m_grounded && m_crouching )
			walkDirection = Vector3.zero;

        m_rigidBody.velocity = new Vector2(walkDirection.x * m_speed, m_rigidBody.velocity.y);

        bool walkingOnGround = false;
		m_walking = walkDirection != Vector3.zero;
		if (m_walking)
        {
            if (m_faceWalkingDirection)
            {
                transform.localScale = new Vector3(walkDirection.x, 1.0f, 1.0f); 
            }

			walkingOnGround = m_grounded;

        }
        if ( walkingOnGround )
        {
	        // if walk loop isn't playing, play it     
			if ( m_soundWalkSource == null || m_soundWalkSource.isPlaying == false )
				m_soundWalkSource = SystemAudio.Play(m_soundWalk);
        }
        else 
		{
			StopWalkSound();
        }

    }


    public void Jump()
    {
		if ( m_crouching )
			return;

        if (m_grounded || m_lateJumpTimer > 0.0f)
        {
			SystemAudio.Play(m_soundJump);
            m_rigidBody.velocity = new Vector2(m_rigidBody.velocity.x, m_jumpForce);
            m_grounded = false;
        }
        else
        {
            m_earlyJumpTimer = m_earlyJumpToleranceTime;
        }
    }

    public bool IsGrounded()
    {
        return m_grounded;
    }

    void StopWalkSound()
	{
		if ( m_soundWalkSource != null &&  m_soundWalkSource.isPlaying )
		{
			SystemAudio.Stop(m_soundWalkSource,0.1f);
			m_soundWalkSource = null;
		}
    }

    void OnDisable()
    {
		StopWalkSound();
    }
    void OnDestroy()
	{
		StopWalkSound();
    }

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

    void Awake()
    {
        m_rigidBody = GetComponent<Rigidbody2D>();
    }

    void Update()
    {
        if (m_earlyJumpTimer > 0.0f)
        {
            m_earlyJumpTimer -= Time.deltaTime;
        }

        if (m_lateJumpTimer > 0.0f)
        {
            m_lateJumpTimer -= Time.deltaTime;
        }
    }

    void FixedUpdate()
    {

        RaycastHit2D hitInfo = Physics2D.BoxCast(transform.position, m_groundBoxDetectSize, 0.0f, Vector3.down, m_groundDetectDistance, LayerMask.GetMask("Ground"));
        if (hitInfo.collider != null)
        {
            if (m_rigidBody.velocity.y <= 0.0f)
            {
                if (!m_grounded)
                {
                    m_grounded = true;


                    if (m_earlyJumpTimer > 0.0f)
                    {
                        m_earlyJumpTimer = 0.0f;
                        Jump();
                    }
                    else 
					{
						SystemAudio.Play(m_soundLand);       
					}
                }
            }
        }
        else
        {
            if (m_rigidBody.velocity.y < 0.0f)
            {
                if (m_grounded)
                {
                    // Falling
                    m_lateJumpTimer = m_lateJumpToleranceTime;
                    m_grounded = false;                
                }
            }
        }
    }
}
