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

public class PlayerInteractionHandler : MonoBehaviour
{
    public delegate void InteractableEvent(InteractableEventArgs args);

    public static event InteractableEvent OnInteractableLook, OnInteractableUnlook, OnInteract;

    public float MaxInteractionDistance = 10f;
    public int UpdatesPerSecond = 20;

    public Camera MainCamera;
    private GameObject interacting;
    private bool coroutineRunning;
    private bool runFirstTime;

    private void Start()
    {
        StartCoroutine(UpdateInteractions());
        coroutineRunning = true;
        runFirstTime = true;
    }

    private void Update()
    {
        if(Input.GetKeyDown(KeyCode.F))
        {
            Interact();
        }
    }

    private void OnDisable()
    {
        coroutineRunning = false;
    }

    private void OnEnable()
    {
        if(!coroutineRunning && runFirstTime)
        {
            StartCoroutine(UpdateInteractions());
            coroutineRunning = true;
        }
    }

    private void Interact()
    {
        if (interacting != null)
        {
            interacting.GetComponent<Interactable>().Interact();
            OnInteracted(new InteractableEventArgs(interacting));
            PlayerAnimationHandler.PlayAnim("Take");
        }
    }

    protected virtual void OnInteractableLooked(InteractableEventArgs args)
    {
        if (OnInteractableLook != null)
            OnInteractableLook(args);
    }

    protected virtual void OnInteractableUnlooked(InteractableEventArgs args)
    {
        if (OnInteractableUnlook != null)
            OnInteractableUnlook(args);
    }

    protected virtual void OnInteracted(InteractableEventArgs args)
    {
        if (OnInteract != null)
            OnInteract(args);
    }

    IEnumerator UpdateInteractions()
    {
        while (true)
        {
            Ray ray = new Ray(MainCamera.transform.position, MainCamera.transform.forward);
            RaycastHit hitInfo;
            if (Physics.Raycast(ray, out hitInfo, MaxInteractionDistance, LayerMask.GetMask("Interactables"), QueryTriggerInteraction.Collide))
            {
                OnHitInteractable(hitInfo);
            }
            else
            {
                OnInteractableLost();
            }
            yield return new WaitForSeconds(1.0f / UpdatesPerSecond);
        }
    }


    void OnHitInteractable(RaycastHit info)
    {
        if(info.collider.gameObject == null)
        {
            OnInteractableLost();
        }
        if (interacting == null || interacting != info.collider.gameObject)
        {
            interacting = info.collider.gameObject;
            OnInteractableLooked(new InteractableEventArgs(interacting));

            Interactable inter = interacting.GetComponent<Interactable>();

            if (inter != null)
                InteractionComment.Show(interacting.GetComponent<Interactable>().LookComment);
        }
    }

    void OnInteractableLost()
    {
        if (InteractionComment.Visible)
            InteractionComment.Hide();
        if (interacting != null)
        {
            OnInteractableUnlooked(new InteractableEventArgs(interacting));
            interacting = null;
            //Debug.Log("Lost Interactable");
        }
    }
}

public class InteractableEventArgs
{
    public GameObject HitGameObject { get; private set; }
    public Interactable HitInteractable
    {
        get
        {
            return HitGameObject.GetComponent<Interactable>();
        }
    }


    public InteractableEventArgs(GameObject hit)
    {
        HitGameObject = hit;
    }
}