using System;
using System.Collections.Generic;
using Intrepid.GameManagers;
using Intrepid.Gameplay.Codex.Knowledge;
using Intrepid.Gameplay.Codex.Knowledge.Events;
using Intrepid.Gameplay.Codex.Visual;
using Intrepid.Gameplay.Codex.Visual.Events;
using Intrepid.SimpleEvents;
using UnityEngine;

namespace Intrepid.Gameplay.Codex
{
    /// <summary>
    /// Runtime owner of what the CODEX currently knows.
    /// This is intentionally separated from PDA runtime state.
    /// </summary>
    public class CodexRuntime : EventListener
    {
        [SerializeField] private CodexOntology ontology = new();
        [SerializeField] private PictorialProtocolInventory pictorialProtocols = new();

        public CodexOntology Ontology => ontology;
        public PictorialProtocolInventory PictorialProtocols => pictorialProtocols;

        public IReadOnlyList<CodexConceptTag> KnownConcepts => ontology.KnownConcepts;
        public IReadOnlyList<PictorialProtocolTag> KnownPictorialProtocols => pictorialProtocols.KnownProtocols;

        public bool Knows(CodexConceptTag concept) => ontology.Knows(concept);
        public bool Knows(PictorialProtocolTag protocol) => pictorialProtocols.Knows(protocol);

        protected override void InitializeVariables()
        {
        }

        protected override void OnBootstrap()
        {
        }

        protected override void Subscriptions()
        {
        }

        public void Learn(CodexConceptTag concept, bool raiseEvent = true)
        {
            if (concept.IsNull()) return;

            if (Knows(concept)) return;

            ontology.Learn(concept);
            
            if (!raiseEvent) return;
            Proxy.Instance.EventBus.Raise(new CodexConceptLearnedEvent
            {
                Concept = concept,
            });
        }

        public void Unlock(PictorialProtocolTag protocol, bool raiseEvent = true)
        {
            if (protocol.IsNull()) return;

            if (Knows(protocol)) return;

            pictorialProtocols.Unlock(protocol);

            if (!raiseEvent) return;
            Proxy.Instance.EventBus.Raise(new PictorialProtocolUnlockedEvent
            {
                Protocol = protocol,
            });
        }
    }
}
