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

public class BenControls : MonoBehaviour
{

    public enum State { Normal, Sprinting, Interacting}

    private State currentState = State.Normal;

    [Header("Settings")]
    [SerializeField] private float moveSpeed;

    [Header("Setup")]
    [SerializeField] private Animator animator;
    [SerializeField] private Rigidbody2D myRigidbody;

    [Header("Movement")]
    private Vector2 moveVector;
    private float previousSpeed = 0f;

    [Header("Scale Handling")]
    [SerializeField] private float scalePosStart = -4.2f;
    [SerializeField] private float scalePosEnd = 0.33f;
    [SerializeField] private float scaleMin = 0.8f;

    [Header("Sprinting")]
    [SerializeField] private float sprintSpeedModifier = 1.4f;
    [SerializeField] private float sprintTime = 0.2f;
    private float sprintTimerCurrent = 0f;

    [Header("Interactions")]
    private Interactible currentInteractible = null;


    // Update is called once per frame
    void Update ()
    {

        HandleState();

        HandleScale();
	}


    private void FixedUpdate()
    {

        Move();
    }


    private void HandleState()
    {
        switch (currentState)
        {
            case State.Normal:

                HandleMovementInput();

                HandleInteracting();

                HandleSprintStart();

                break;

            case State.Sprinting:

                HandleMovementInput();

                SprintUpdate();
                break;

            case State.Interacting:
                break;

            default:
                break;
        }
    }


    public void SetState(State state)
    {

        OnStateExit(currentState);

        OnStateEnter(state);

        currentState = state;
    }


    private void OnStateExit(State state)
    {

        switch (state)
        {
            case State.Normal:
                break;

            case State.Sprinting:
                break;

            case State.Interacting:
                break;

            default:
                break;
        }
    }

    private void OnStateEnter(State state)
    {

        switch (state)
        {
            case State.Normal:
                break;

            case State.Sprinting:
                sprintTimerCurrent = 0f;
                break;

            case State.Interacting:
                moveVector = Vector2.zero;
                break;

            default:
                break;
        }
    }



    private void HandleMovementInput()
    {

        moveVector = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical")) * moveSpeed;
    }


    private void Move()
    {

        animator.SetFloat("SpeedX", moveVector.x);

        animator.SetFloat("SpeedY", moveVector.y);

        animator.SetFloat("Velocity", moveVector.magnitude);

        SetHeadDirection();
        
        moveVector *= Time.deltaTime;

        myRigidbody.MovePosition(transform.position + new Vector3(moveVector.x, moveVector.y));

        previousSpeed = moveVector.magnitude;

        moveVector = Vector2.zero;
    }


    private void SetHeadDirection()
    {
        if(moveVector.x == 0 && moveVector.y == 0)
        {
            animator.SetInteger("Direction", 2);
        }
        else if(Mathf.Abs(moveVector.x) > Mathf.Abs(moveVector.y))
        {
            if(moveVector.x > 0)
            {
                animator.SetInteger("Direction", 1);
            }
            else
            {
                animator.SetInteger("Direction", 3);
            }
        }
        else
        {
            if(moveVector.y > 0)
            {
                animator.SetInteger("Direction", 0);
            }
            else
            {
                animator.SetInteger("Direction", 2);
            }
        }
    }


    private void HandleSprintStart()
    {
        
        if (previousSpeed <= 0.1f && moveVector.magnitude > moveSpeed / 4)
        {

            moveVector *= sprintSpeedModifier;

            SetState(State.Sprinting);
        }

    }


    private void SprintUpdate()
    {
        
        sprintTimerCurrent += Time.deltaTime;

        if(sprintTimerCurrent >= sprintTime)
        {
            SetState(State.Normal);
            return;
        }

        moveVector *= sprintSpeedModifier;
    }


    private void HandleScale()
    {

        float posY = transform.position.y;

        float range = scalePosEnd - scalePosStart;

        if (range == 0)
        {

            Debug.LogError("Range was 0, not acceptable!");

            return;
        }

        float lerpPos = (posY - scalePosStart) / range;

        float scale = Mathf.Lerp(1, scaleMin, lerpPos);

        transform.localScale = new Vector3(scale, scale, scale);
    }


    private void HandleInteracting()
    {
        if(currentInteractible != null && Input.GetButtonDown("Submit"))
        {
            if (currentInteractible.BlocksPlay)
            {
                SetState(State.Interacting);
            }
            currentInteractible.Interact();
            if (currentInteractible != null && currentInteractible.OneShot)
            {
                currentInteractible = null;
            }
        }
    }


    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.gameObject.layer == 8)
        {
            Interactible triggeredInteractible = collision.gameObject.GetComponent<Interactible>();
            if(triggeredInteractible != null)
            {
                currentInteractible = triggeredInteractible;
            }
        }
    }


    private void OnTriggerExit2D(Collider2D collision)
    {

        if (collision.gameObject.layer == 8)
        {
            Interactible triggeredInteractible = collision.gameObject.GetComponent<Interactible>();
            if (triggeredInteractible == currentInteractible)
            {
                currentInteractible = null;
            }
        }
    }

}
