using System;
using Intrepid.GameManagers;
using Intrepid.Gameplay.Entities.Player.PDA.Events;
using Intrepid.SimpleEvents;
using Intrepid.Utilities;
using UnityEngine;

namespace Intrepid.Gameplay.Entities.Player.PDA.UI
{
    public class PDADeviceUI : EventListener, IPDASystemBootEvents, IPDASystemShutdownEvents
    {
        [GroupInjections, SerializeField] private PDADevice device;
        [GroupInjections, SerializeField] private PDAOperationalSystemUI operationalSystem;
        [GroupInjections, SerializeField] private PDALoadingProcessUI loadingProcess;
        
        private Func<MonoBehaviour> TargetApplicationLoader { get; set; } 
        private PDAApplicationUI _targetApplication;
        private PDAApplicationUI TargetApplication => _targetApplication ?? operationalSystem;
        private bool DeviceRunning { get; set; }
        
        public bool ApplicationOverriding { get; set; }

        private void Update()
        {
            if (!DeviceRunning) return;
            loadingProcess.UpdateLoadingProcess();
            TargetApplication.UpdateApplication(device.PDAInputs);
        }

        private void LateUpdate()
        {
            if (!DeviceRunning) return;
            TargetApplication.UpdateTheme();
            TargetApplication.LateUpdateApplication(device.PDAInputs);
        }

        protected override void InitializeVariables()
        {
            DeviceRunning = false;
        }

        protected override void OnBootstrap()
        {
        }

        protected override void Subscriptions()
        {
            Subscribe<PDAEnterApplicationEvent>(WhenPDAEnterApplication);
            Subscribe<PDAExitCurrentApplicationEvent>(WhenPDAExitApplication);
        }

        private void WhenPDAEnterApplication(PDAEnterApplicationEvent e)
        {
            operationalSystem.WhenExiting();
            TargetApplicationLoader = device.ApplicationLoader(e.ContentTag, operationalSystem.transform.parent);
            loadingProcess.StartLoading(LoadingProcess);
        }
        
        private void WhenPDAExitApplication(PDAExitCurrentApplicationEvent e)
        {
            if (ApplicationOverriding || _targetApplication is null)
            {
                if (!DeviceRunning) return;
                Proxy.Instance.EventBus.Raise(new PDADeviceShutdownEvent());
                return;
            }
            _targetApplication.WhenExiting();
            Destroy(_targetApplication.gameObject);
            _targetApplication = null;
            loadingProcess.StartLoading(LoadingProcess);
        }
        
        private Func<bool> LoadingProcess()
        {
            if (TargetApplicationLoader is not null)
            {
                _targetApplication = (PDAApplicationUI)TargetApplicationLoader();
                TargetApplicationLoader = null;
                operationalSystem.gameObject.SetActive(false);
                TargetApplication.gameObject.SetActive(true);
            }
            else if (!ApplicationOverriding)
            {
                TargetApplication.gameObject.SetActive(true);
                operationalSystem.PrepareEnvironment(device.GetAvailableContentTags());
            }
            TargetApplication.WhenEntering();
            return () => TargetApplication.IsLoading;
        }

        // Before Push Action
        public void WhenPreparingSystemBoot()
        {
            loadingProcess.StraightBlock();

            var overrideContentTag = device.GetOverrideContentTag();
            if (overrideContentTag is not null)
            {
                ApplicationOverriding = true;
                _targetApplication = (PDAApplicationUI)device
                    .ApplicationLoader(overrideContentTag, operationalSystem.transform.parent)();
                operationalSystem.gameObject.SetActive(false);
            }
            else
            {
                ApplicationOverriding = false;
            }

            TargetApplication.WhenPreparingSystemBoot();
        }

        // After Push Action
        public void WhenRunningSystemBoot()
        {
            DeviceRunning = true;
            TargetApplication.WhenRunningSystemBoot();
            loadingProcess.StartLoadingNoAnimation(LoadingProcess);
        }

        // Before Pop Action
        public void WhenPreparingSystemShutdown()
        {
            DeviceRunning = false;
            loadingProcess.BlockageBlock();
            TargetApplication.WhenPreparingSystemShutdown();
        }

        // After Pop Action
        public void WhenRunningSystemShutdown()
        {
            TargetApplication.WhenRunningSystemShutdown();
            _targetApplication = null;
            TargetApplicationLoader = null;
            operationalSystem.gameObject.SetActive(true);
            ApplicationOverriding = false;
        }
    }
}