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

namespace Machete {

	public class InputManager : MonoBehaviour {

    delegate void UpdateHandler();
    UpdateHandler updateHandler;

    Message currentMessage;

    public GameObject PlanningUI;
    public GameObject ExecutePlanButton;
    public bool ValidPlan {
      get { return validPlan; }
      set {
        validPlan = value;
        ExecutePlanButton.SetActive(validPlan);
      }
    }
    bool validPlan;

    void Start() {
      // Singleton it.
      updateHandler = WatchingUpdate;
    }

    void LateUpdate() {
      if (Input.GetKeyDown(KeyCode.Escape)) {
        SceneManager.LoadScene("Menu");
      }

      updateHandler();
    }

    void WatchingUpdate() {
      if (Input.GetMouseButtonUp(0)) {
        Desk desk = GetHitInLayer<Desk>("Desk");
        // Check if we are clicking a desk with a message being planned.
        if (desk != null && desk.HasMessage && desk.Message.Planning) {
          currentMessage = desk.Message;
          currentMessage.MarkEndPoints(true);
          PlanningUI.SetActive(true);
          updateHandler = PlanningUpdate;
        }
      }
    }

    void PlanningUpdate() {
      if (Input.GetMouseButtonUp(0)) {
        Desk desk = GetHitInLayer<Desk>("Desk");
        if (desk != null) {
          currentMessage.InteractWithDesk(desk);
          ValidPlan = currentMessage.IsValidPlan;
        }
      } else if (Input.GetMouseButtonUp(1)) {
        Desk desk = GetHitInLayer<Desk>("Desk");
        if (desk != null && desk == currentMessage.Desk) {
          currentMessage.RemoveLast(CommandType.Wait, desk);
        }
      }
    }

    public void ExecutePlan() {
      if (currentMessage != null) {
        currentMessage.Execute();
        currentMessage = null;
        updateHandler = WatchingUpdate;
        PlanningUI.SetActive(false);
        ExecutePlanButton.SetActive(false);
      }
    }

    T GetHitInLayer<T>(string layer) where T : MonoBehaviour {
      Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
      RaycastHit hit;
      int layerMask = LayerMask.GetMask(layer);

      if (Physics.Raycast(ray, out hit, 100, layerMask)) { // TODO: make it shorter.
        return hit.collider.GetComponent<T>();
      }

      return null;
    }
	}
}
