using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement;

public class BaseCharacterController : MonoBehaviour {

    public Transform spawnPoint;
    public BaseCharacterController friend; 
    WaveGenerator IntervalScript;
    public Animator playerAnimator;

    public enum STATE { IDLE = 0, MOVINGLEFT, MOVINGRIGHT, INAIR, DEAD, PAUSED, WON }
    public STATE state = 0;

    private Rigidbody2D rb;

    public AnimationCurve accelerationRate;
    public AnimationCurve jumpRate;
    public AnimationCurve deathLerp;

    [SerializeField]
    private float maxMovementSpeed;
    [SerializeField]
    private float maxJumpHeight;
    [SerializeField]
    private float jumpSpeed;
    [SerializeField]
    private float deathLerpSpeed;
    [SerializeField]
    private float RaycastLength;
    public LayerMask layerMask;

    private float horizontal;
    private float vertical;

    private float currentJumpVelocity;

    private float acceletationPercent;
    private float jumpPercent;
    private float deathPercentage;

    Vector3 deathLocation;

    public bool Jump;
    private bool canJump = true;

    // Use this for initialization
    void Awake ()
    {
        IntervalScript = GameObject.Find("Wave Generator").GetComponent<WaveGenerator>();
        playerAnimator = GetComponent<Animator>();

        rb = GetComponent<Rigidbody2D>();

        horizontal = 0;
        vertical = 0;

        deathPercentage = 0;
	}

    // Update is called once per frame
    void FixedUpdate()
    {
        if (state != STATE.DEAD && state != STATE.WON)
        {
            playerAnimator.SetBool("Dead", false);
            if (Jump && jumpPercent < 2.0f)
            {
                jumpPercent += (Time.fixedDeltaTime * jumpSpeed);
            }

            rb.velocity = new Vector2(horizontal * maxMovementSpeed, jumpRate.Evaluate(jumpPercent) * maxJumpHeight);

            RaycastHit2D hit = Physics2D.Raycast(new Vector3(transform.position.x, transform.position.y - (transform.localScale.y / 2), transform.position.z), -Vector2.up, RaycastLength, layerMask);

            if (hit && jumpPercent > 1)
            {
                Jump = false;
                canJump = true;
                jumpPercent = 0;
                state = STATE.IDLE;
            }

            Debug.DrawRay(new Vector3(transform.position.x, transform.position.y - (transform.localScale.y / 2), transform.position.z), -Vector2.up, new Color(1, 0, 0), 0.1f);

            //Player Animation

            //Idle/Booping
            if (state == STATE.IDLE && IntervalScript.hitInterval == true)
            {
                playerAnimator.SetTrigger("SwapOnBeat");
            }

            //Left and Right Walking
            if (state == STATE.MOVINGLEFT || state == STATE.MOVINGRIGHT)
            {
                playerAnimator.SetBool("Walking", true);

                if (state == STATE.MOVINGLEFT)
                {
                    GetComponent<SpriteRenderer>().flipX = true;
                }
                else if (state == STATE.MOVINGRIGHT)
                {
                    GetComponent<SpriteRenderer>().flipX = false;
                }
            }
            else
            {
                playerAnimator.SetBool("Walking", false);
            }

            //Jumping
            if (state == STATE.INAIR)
            {
                playerAnimator.SetBool("Jumping", true);
            }
            else
            {
                playerAnimator.SetBool("Jumping", false);
            }


            if (transform.position.y < -200.0f)
            {
                Kill();
            }
        }

        else if (state == STATE.DEAD)
        {
            playerAnimator.SetBool("Dead", true);
            if (deathPercentage < 1)
            {
                deathPercentage += Time.deltaTime * deathLerpSpeed;
                float currentDeathLerp = deathLerp.Evaluate(deathPercentage);

                transform.position = Vector2.Lerp(deathLocation, spawnPoint.position, currentDeathLerp);
            }
            else
                Respawn();
        }

        else if (state == STATE.WON)
        {
            rb.velocity = new Vector2(0, 0);

            playerAnimator.SetBool("Walking", false);
            playerAnimator.SetBool("Won", true);
        }
    }

    public void Move(float _horizontal, float _vertical)
    {
        if (state != STATE.DEAD && state != STATE.WON)
        {
            horizontal = _horizontal;
            vertical = _vertical;

            if (horizontal > 0)
            {
                if (state < (STATE)3)
                    state = STATE.MOVINGRIGHT;
            }
            else if (horizontal < 0)
            {
                if (state < (STATE)3)
                    state = STATE.MOVINGLEFT;
            }
            else if (state != STATE.INAIR)
            {
                state = STATE.IDLE;
            }
            if (vertical > 0 && canJump)
            {
                Jump = true;
                state = STATE.INAIR;
            }
        }

        else if(state == STATE.WON)
        {
            horizontal = 0;
            vertical = 0;
        }
    }

    void CalculateRayLocations()
    {

    }

    void OnCollisionEnter2D(Collision2D col)
    {
        if (col.gameObject.tag == "Deadly")
        {
            Kill();
        }
    }

    void OnCollisionStay2D(Collision2D col)
    {
        if (col.gameObject.tag == "Moving")
        {
            gameObject.transform.parent = col.gameObject.transform;
        }
    }
    void OnCollisionExit2D(Collision2D col)
    {
        canJump = false;
        if (!Jump)
        {
            Jump = true;
            jumpPercent = 1.55f;

            if (state != STATE.DEAD)
                state = STATE.INAIR;
        }

        if (col.gameObject.tag == "Moving")
        {
            gameObject.transform.parent = null;
        }
    }

    void OnTriggerEnter2D(Collider2D col)
    {
        if (col.gameObject.tag == "Deadly")
        {
            Kill();
        }
    }
    void OnTriggerExit2D( Collider2D other)
    {
        canJump = false;
        if (!Jump)
        {
            Jump = true;
            jumpPercent = 1.55f;

            if (state != STATE.DEAD)
                state = STATE.INAIR;
        }
    }

    public void Kill()
    {
        state = STATE.DEAD;
        if (friend.state != STATE.DEAD)
            friend.Kill();

        GetComponent<Collider2D>().enabled =      false;
        GetComponent<Rigidbody2D>().isKinematic = true;

        Color temp = GetComponent<SpriteRenderer>().material.color;
        GetComponent<SpriteRenderer>().material.color = new Color(temp.r, temp.g, temp.b, 0.6f);

        deathLocation = transform.position;
        deathPercentage = 0;
    }

    public void Win()
    {
        state = STATE.WON;
    }

    void Respawn()
    {
        transform.position = new Vector3(spawnPoint.position.x, spawnPoint.position.y);

        state = STATE.IDLE;
        GetComponent<Collider2D>().enabled = true;
        GetComponent<Rigidbody2D>().isKinematic = false;

        Color temp = GetComponent<SpriteRenderer>().material.color;
        GetComponent<SpriteRenderer>().material.color = new Color(temp.r, temp.g, temp.b, 1.0f);
    }

    bool AboveGround()
    {
        RaycastHit2D hit = Physics2D.Raycast(new Vector3(transform.position.x, transform.position.y - (transform.localScale.y / 2), transform.position.z), -Vector2.up, 0.5f, layerMask);
        return hit;
    }
}
