using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Events;

public class DialogueManager : MonoBehaviour
{
    [SerializeField]
    public string SpeakerName;

    [SerializeField]
    public LanguageDetector<MultiDialogue> languageDetector;

    /* We user object CLONED TO PREVENT overwritting changes in main object inassets */
    [SerializeField]
    public MultiDialogue Dialogue;

    // List<Key<dialogue No, dialogue step No>, Value : UnityEvent>
    public List<IndexValuePair<IndexValuePair<int, int>, UnityEvent>> EndactionEventList;

    [SerializeField] public KeyCode keyToOpen = KeyCode.E;

    public bool CanBeOpened = true;

    /// <summary>
    /// This flag tell that manager will open dialogue automatically after
    /// - beeing in collision range
    /// - when dialogue is closed
    /// - when Player press KeyToOpen button
    /// 
    /// Change var status in other sctipt if you want to use other triggers to open dialogue
    /// </summary>
    public bool OpenInDefaultWay = true;

    public virtual void Start()
    {
        Dialogue = Instantiate(languageDetector.DetectInstanceBasedOnLanguage());
        Dialogue.SetSpeakerName(SpeakerName);

        Dialogue.Dialogues.ForEach(dial => dial.Value.SetActionAfterDialogueStep(dial.Key, dial.Value.ResetDialogue));  // reset dial 
    }


    public void Update()
    {
        if (OpenInDefaultWay && Input.GetKeyDown(keyToOpen) && OpenPanelCondition())
            OpenDialoguePanel();
    }


    public virtual void OnTriggerEnter2D(Collider2D collision)
    {
        // don't listen when component is disabled
        if (ComponentEnabledCondition())
            return;

        if (collision.gameObject.tag == "Player")
        {
            CanBeOpened = true;

            SpeakerName = collision.gameObject.name;
        }
    }
    public virtual void OnTriggerExit2D(Collider2D collision)
    {
        // don't listen when component is disabled
        if (ComponentEnabledCondition())
            return;

        if (collision.gameObject.tag == "Player")
        {
            CanBeOpened = false;

            if (GetCurrentDialoguePanelStatus())
            {
                Debug.Log("Close dialog - defaulty way");
                Dialogue.BreakDialogueStep();
            }
        }
    }

    public void OpenDialoguePanel()
    {
        if(OpenPanelCondition())
            gameObject.GetComponent<DialogueManager>().Dialogue.StartDialogue();
    }
    public virtual bool OpenPanelCondition()
    {
        /*
         * Conditions:
         * - player is in collision range
         * - panel assigned to next sentence in dialogue must be closed 
         */
        return IsInRangeCondition() && !GetCurrentDialoguePanelStatus();
    }

    public bool IsInRangeCondition()
    {
        return CanBeOpened;
    }
    protected virtual bool ComponentEnabledCondition()
    {
        return !gameObject.GetComponent<DialogueManager>().enabled;
    }

    /// <summary>
    /// Opened = 1
    /// Closed = 0
    /// </summary>
    /// <returns></returns>
    public bool GetCurrentDialoguePanelStatus()
    {
        var multiDialStatius = Dialogue.DialogueStepStatus();

        return Dialogue
            .Dialogues
            .Where(dialogue => dialogue.Key == multiDialStatius.Item1)
            .First()
            .Value
            .DialogueSteps[multiDialStatius.Item2].DialogueController.CurrentPanel != null;
    }
}