using System.Linq;
using DialogueSystem;
using DialogueSystem.Notes;
using Hazards;
using UniRx;
using UnityEngine;
using UnityEngine.Events;

namespace Tutorials
{
    /// <summary>
    /// This script is coupled to the SpawnHazards, as well as to the TutorialScriptableObject script.
    ///
    /// How to use:
    /// 1. Add this script to a gameObject, that will serve as an instantiator for the tutorial.
    /// 2. Create a TutorialScriptableObject in the Project window (Create->ScriptableObject->TutorialScriptableObject).
    /// 3. Assign the parameters to the TutorialScriptableObject (see script for details).
    /// 4. Add the TutorialScriptableObject as a reference to this object.
    /// 
    /// </summary>
    public class TutorialInstantiator : MonoBehaviour
    {
        public TutorialScriptableObject tutorialSO;

        public bool omitWhenAlreadyInArchive;

        /// <summary>
        /// When setting this to true, the script will not open the tutorial panel by itself, assuming to setup an event
        /// and invoke the OpenTutorialAndDestroyInstantiator function from there.
        /// </summary>
        public bool onEventCall;
        
        private void Start()
        {
            SpawnHazards spawnHazards = SpawnHazards.Instance;
            
            Debug.Log("Tutorial Instantiator available");
            
            if (omitWhenAlreadyInArchive && IsInArchive())
            {
                Destroy(gameObject); 
            }

            // For some tutorials we might want to have events that trigger them.
            // These Events are specified in the class that should trigger the event.
            // To open the panel call: OpenTutorialAndDestroyInstantiator()
            if (onEventCall)
                return;
            
            if (spawnHazards)
            {
                spawnHazards.hazardSpawned
                    .Delay(System.TimeSpan.FromSeconds(0.75f))
                    .Subscribe(spawned =>
                    {
                        Debug.Log($"spawned null: {spawned == null}");
                        if (spawned != null)
                        {
                            Debug.Log($"spawned.actionName: {spawned.actionName}");
                            if (tutorialSO.triggerActions.Contains(spawned.actionName))
                            {
                                OpenTutorialAndDestroyInstantiator();
                            }
                        }
                    })
                    .AddTo(this); // cancel the subscription when object has been destroyed

            }
            
            
            if (tutorialSO.triggerActions[0] == "Start")
            {
                Observable.Timer(System.TimeSpan.FromSeconds(1f))
                    .Subscribe(_ =>
                    {
                        OpenTutorialAndDestroyInstantiator();
                    })
                    .AddTo(this);
            }
            
        }

        public void OpenTutorialAndDestroyInstantiator()
        {
            DialogueManager.Instance.OpenTutorialWindow(tutorialSO);
            GenericScriptableObjectArchive.AddToArchive(tutorialSO, "Tutorial");
            Destroy(gameObject);
        }

        private bool IsInArchive()
        {
            var archivedItems = GenericScriptableObjectArchive
                .GetArchivedItems<TutorialScriptableObject>("Tutorial", "Tutorials");

            foreach (TutorialScriptableObject item in archivedItems)
            {
                if (item == tutorialSO)
                    return true;
            }

            return false;
        }
        
    }
}
