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

public class PlayerMovement : MonoBehaviour {

    public float maxSpeed;
    public float drag;
    public float acceleration;
    public float jumpForce;
    public float attackImpulse;
    public float attackUpImpulse;
    public float attackDownImpulse;
    public Transform trailTransform, stunTrailTransform, swordTrailTransform, upwardsTrailTransform, downSwordTrailTransform;

    public float hitDisabledTime;
    public float hitKnockback;

    Rigidbody2D rigidBody;
    Animator anim;
    bool facingRight = true;
    bool attacking = false;
    public bool jumping = false;
    bool moving = false;
    bool isHit;

    SamuraiWave wave;

    [SerializeField]private AudioSource runSound;
    [SerializeField]private AudioSource attackSound;
    [SerializeField]private AudioSource jumpStartSound;
    [SerializeField]private AudioSource jumpLandSound;
    [SerializeField]private AudioSource hitSound;

    public bool Attacking {
        get { return attacking; }
    }

    public bool IsHit
    {
        get { return isHit; }
    }

	// Use this for initialization
	void Start () {
        rigidBody = GetComponent<Rigidbody2D>();
        anim = GetComponent<Animator>();
        wave = GetComponent<SamuraiWave>();
	}
	
	// Update is called once per frame
	void Update () {
        if (!attacking && !wave.lightOnAnimating) {
            if (Input.GetButtonDown("Attack")) {
                Attack();
            }
            if (Input.GetButtonDown("Jump")) {
                Jump();
            }
            if (Input.GetAxisRaw("Horizontal") != 0) {
                if (!moving) {
                    moving = true;
                    anim.SetBool("Moving", true);
                    
                }
                Move(Input.GetAxisRaw("Horizontal"));
            }
            
        }
        else {
            rigidBody.velocity = (new Vector2(rigidBody.velocity.x * drag, rigidBody.velocity.y));
        }

        if (moving && Input.GetAxisRaw("Horizontal") == 0) {
            moving = false;
            anim.SetBool("Moving", false);
        }
        if (jumping) {
            RaycastHit2D hit = Physics2D.BoxCast(transform.position, new Vector2(0.9f, 0.01f), 0, -Vector2.up, 0.1f, 1 << 8);
            if (hit.collider != null) {
                jumping = false;
                anim.SetBool("Falling", false);

                jumpLandSound.Play();
            }
        }
	}

    public void PlayRunSound() {
        runSound.Play();
    }

    void Jump() {
        RaycastHit2D hit = Physics2D.BoxCast(transform.position, new Vector2(0.9f,0.01f), 0,  -Vector2.up, 0.1f, 1 << 8);
        if (hit.collider != null) {
            if (runSound.isPlaying)
                runSound.Stop();
            jumpStartSound.Play();
            rigidBody.AddForce(Vector2.up * jumpForce);
            anim.SetTrigger("Jump");
            anim.SetBool("Falling", true);
            Invoke("CheckJump", 0.05f);
        }
    }

    void CheckJump() {
        jumping = true;
    }

    void Move(float direction) {
        float speed = rigidBody.velocity.x;
        //Debug.Log(speed);
        if (speed < 0)
            speed = Mathf.Max(speed + acceleration * direction, -maxSpeed);
        else if (speed > 0)
            speed = Mathf.Min(speed + acceleration * direction, maxSpeed);
        else
            speed = speed + acceleration * direction;
        rigidBody.velocity = (new Vector2(speed, rigidBody.velocity.y));

        if (direction > 0 && !facingRight)
            Flip();
        else if (direction < 0 && facingRight)
            Flip();
    }

    void Flip()
    {
        facingRight = !facingRight;
        Vector3 theScale = transform.localScale;
        Vector3 trailScale = trailTransform.localScale;
        Vector3 stunTrailScale = stunTrailTransform.localScale;
        Vector3 swordTrailScale = swordTrailTransform.localScale;
        Vector3 upTrailScale = upwardsTrailTransform.localScale;
        Vector3 downTrailScale = downSwordTrailTransform.localScale;

        theScale.x *= -1;
        trailScale.x *= -1;
        stunTrailScale.x *= -1;
        swordTrailScale.x *= -1;
        upTrailScale.x *= -1;
        downTrailScale.x *= -1;

        transform.localScale = theScale;
        trailTransform.localScale = trailScale;
        stunTrailTransform.localScale = stunTrailScale;
        swordTrailTransform.localScale = swordTrailScale;
        upwardsTrailTransform.localScale = upTrailScale;
        downSwordTrailTransform.localScale = downTrailScale;
    }

    public bool CanLightOn() {
        if (!attacking && !moving && !jumping) {
            return true;
        }
        return false;
    }

    public void ResetVelocity() {
        rigidBody.velocity = Vector2.zero;
    }

    void Attack() {
        if (!attacking) {
            if (runSound.isPlaying)
                runSound.Stop();
            attackSound.Play();
            rigidBody.velocity = Vector2.zero;
            rigidBody.gravityScale = 0;
            if (Input.GetAxisRaw("Vertical") != 0) {
                if (Input.GetAxisRaw("Vertical") > 0) {
                    anim.SetTrigger("AttackUp");
                    attacking = true;
                    return;
                }
                else {
                    RaycastHit2D hit = Physics2D.BoxCast(transform.position, new Vector2(0.9f, 0.01f), 0, -Vector2.up, 0.1f, 1 << 8);
                    if (Input.GetAxisRaw("Vertical") < 0 && hit.collider == null) {
                        anim.SetTrigger("AttackDown");
                        attacking = true;
                        return;
                    }
                }
                
            }
            
            anim.SetTrigger("PlayerAttack");
            attacking = true;

        }
    }

    //used in the animation
    public void FinishAttack() {
        attacking = false;
        rigidBody.gravityScale = 1;
        rigidBody.velocity = Vector2.zero;
    }

    public void AttackImpulse() {
        int direction = facingRight ? 1 : -1;
        rigidBody.AddForce(transform.right * attackImpulse * direction, ForceMode2D.Impulse);
    }

    public void AttackUpImpulse() {
        rigidBody.AddForce(transform.up * attackUpImpulse, ForceMode2D.Impulse);
        rigidBody.gravityScale = 1;
        anim.SetBool("Falling", true);
        Invoke("CheckJump", 0.05f);
    }

    public void AttackDownImpulse() {
        rigidBody.AddForce(-transform.up * attackDownImpulse, ForceMode2D.Impulse);
    }

    public void ApplyDamage ()
    {
        isHit = true;
        hitSound.Play();
        enabled = false;        

        anim.SetBool("Freeze", true);
        anim.SetTrigger("Hit");
        rigidBody.velocity = Vector2.zero;
        if (!facingRight) {
            rigidBody.AddForce(new Vector2(hitKnockback, hitKnockback), ForceMode2D.Impulse);
        }
        else {
            rigidBody.AddForce(new Vector2(-hitKnockback, hitKnockback), ForceMode2D.Impulse);
        }
        trailTransform.gameObject.SetActive(false);
        stunTrailTransform.gameObject.SetActive(true);
        Invoke("RestoreMovement", hitDisabledTime);
    }

    private void RestoreMovement ()
    {
        enabled = true;
        isHit = false;
        anim.SetBool("Freeze", false);
        trailTransform.gameObject.SetActive(true);
        stunTrailTransform.gameObject.SetActive(false);
    }

}
