using UnityEngine;
using System.Collections;
using Framework.Entities;
using Framework.Utility;
using Framework.Extensions;

public class AlchemistPlayerInput : CoreBehaviour 
{
    public class FreezeAction : CoreAction
    {
    }

    public class UnfreezeAction : CoreAction
    {
    }

    private Responsive targetResponsive;

    private GameObject visual;
    private Animator animator;

    private bool freeze = false;
    public JournalDisplay journalDisplay;

	// Use this for initialization
    protected override void InnerAwake() 
    {
        AddGlobalActionHandler<FreezeAction>(this, Freeze);
        AddGlobalActionHandler<UnfreezeAction>(this, Unfreeze);

        this.visual = this.transform.RecursivelyFindChild("Visual").gameObject;
        this.animator = this.visual.GetComponent<Animator>();
	}
	
	// Update is called once per frame
	protected override void InnerUpdate () 
    {
        if (!freeze)
        {
            Vector3 inputVector = new Vector3(
                    BinaryCeil(Input.GetAxis("Horizontal")),
                    0,
                    BinaryCeil(Input.GetAxis("Vertical")));

            if (inputVector.magnitude > 0)
            {
                Interact(new MoveAction(this.transform.position + (this.transform.rotation * inputVector)));
                if (inputVector.z != 0)
                {
                    this.animator.SetFloat("VerticalDirection", inputVector.z);
                }
                if (inputVector.x != 0)
                {
                    this.visual.transform.localScale = new Vector3(Mathf.Abs(this.visual.transform.localScale.x) * inputVector.x, this.visual.transform.localScale.y, this.visual.transform.localScale.z);
                }
            }
            else
            {
                Interact(new StopAction());
                this.animator.Play(this.animator.GetCurrentAnimatorStateInfo(0).fullPathHash, 0, 0.25f);
            }

            this.animator.SetFloat("Speed", this.gameObject.GetComponent<Rigidbody>().velocity.magnitude / 5);

            if (Input.GetKeyDown(KeyCode.J))
            {
                if (journalDisplay.gameObject.activeSelf)
                {
                    journalDisplay.gameObject.SetActive(false);
                }
                else
                {
                    journalDisplay.gameObject.SetActive(true);
                }
            }

            CheckResponsives();
        }
	}

    private void CheckResponsives()
    {
        float currentMinDistance = float.MaxValue;
        Responsive currentNearestResponsive = null;
        Collider[] hitColliders = Physics.OverlapSphere(this.transform.position, 2f);
        for (int i = 0; i < hitColliders.Length; i++)
        {
            GameObject other = hitColliders[i].gameObject;
            Responsive otherResponsive = other.GetComponent<Responsive>();
            if (otherResponsive != null)
            {
                float distance = Vector3.Distance(this.transform.position, other.transform.position);
                if (distance < currentMinDistance)
                {
                    currentMinDistance = distance;
                    currentNearestResponsive = otherResponsive;
                }
            }
        }

        if (currentNearestResponsive != null && currentNearestResponsive != this.targetResponsive)
        {
            if (this.targetResponsive != null)
            {
                this.targetResponsive.Interact(new Responsive.HideNameAction());
            }
            this.targetResponsive = currentNearestResponsive;
            this.targetResponsive.Interact(new Responsive.ShowNameAction());
        }

        if (this.targetResponsive != null)
        {
            if (Input.GetKeyDown(KeyCode.E))
            {
                this.targetResponsive.Interact(new Responsive.RespondAction(this));
            }

            if (currentNearestResponsive == null || currentNearestResponsive != this.targetResponsive)
            {
                this.targetResponsive.Interact(new Responsive.HideNameAction());
                this.targetResponsive = null;
            }
        }
    }

    private void Freeze(FreezeAction action)
    {
        this.freeze = true;
    }

    private void Unfreeze(UnfreezeAction action)
    {
        this.freeze = false;
    }

    private float BinaryCeil(float input)
    {
        if (input > 0)
        {
            return Mathf.Ceil(input);
        }
        else if (input < 0)
        {
            return Mathf.Floor(input);
        }
        else
        {
            return 0;
        }
    }
}
