using System;
using System.Collections;
using Intrepid.Core.UI;
using Intrepid.Core.UI.Dialog;
using Intrepid.GameManagers;
using Intrepid.Gameplay.Entities.Player.ActionBelt.Events;
using Intrepid.Gameplay.Entities.Player.UI;
using Intrepid.Gameplay.Themes;
using Intrepid.Utilities;
using Intrepid.Utilities.Sprite;
using Sirenix.OdinInspector;
using TMPro;
using UnityEngine;

namespace Intrepid.Gameplay.Entities.Player.ActionBelt.UI
{
    public class ActionBeltUI : ManagedWindowUI
    {
        [GroupInjections, SerializeField] private ActionBeltManager actionBeltManager;
        [GroupInjections, SerializeField, PropertySpace] private DialogMinimalUI left;
        [GroupInjections, SerializeField] private DialogMinimalUI right;
        [GroupInjections, SerializeField] private DialogMinimalUI center;
        [GroupInjections, SerializeField] private DialogMinimalUI local;
        [GroupInjections, SerializeField, PropertySpace] private SpriteAnimationController leftIconAnimation;
        [GroupInjections, SerializeField] private SpriteAnimationController rightIconAnimation;
        [GroupInjections, SerializeField] private SpriteAnimationController contentIconAnimation;
        [GroupInjections, SerializeField, PropertySpace] private TextMeshProUGUI actionTextMeshPro;
        [GroupInjections, SerializeField] private NewsTickerUI localNewsTicker;

        private UIActionBeltTheme CurrentTheme { get; set; }
        private Func<ActionEnvelope> GetFocus { get; set; }
        private Func<ActionEnvelope> SneakPeekRight { get; set; }
        private Func<ActionEnvelope> SneakPeekLeft { get; set; }
        private Func<int> GetNumberOfActionsInBelt { get; set; } = () => 0;
        private bool IsOptionActive => GetNumberOfActionsInBelt() > 1;
        
        protected override void InitializeVariables()
        {
            GetFocus = () => actionBeltManager.Focus;
            SneakPeekRight = () => actionBeltManager.PeekRight;
            SneakPeekLeft = () => actionBeltManager.PeekLeft;
            GetNumberOfActionsInBelt = () => actionBeltManager.Count;
        }

        protected override void OnBootstrap()
        {
            UpdateTheme();
        }

        private void UpdateTheme()
        {
            var theme = ThemeManager.Instance.CurrentTheme.ActionBeltTheme;
            if (CurrentTheme == theme) return;
            CurrentTheme = theme;
            left.Theme = theme.Option;
            right.Theme = theme.Option;
            center.Theme = theme.Main;
            local.Theme = theme.Local;
            actionTextMeshPro.color = theme.TextColor;
            localNewsTicker.TextMesh.color = theme.TextColor;
        }

        protected override void Subscriptions()
        {
            Subscribe<ActionBeltShowEvent>(_ => ManagedWindow.Show());
            Subscribe<ActionBeltHideEvent>(_ => ManagedWindow.Hide());
            
            Subscribe<ActionBeltUIToRightEvent>(WhenActionBeltNextRight);
            Subscribe<ActionBeltUIToLeftEvent>(WhenActionBeltNextLeft);
            
            Subscribe<ActionBeltUITakeActionEvent>(WhenActionBeltUITakeAction);
            Subscribe<ActionBeltUIDropEvent>(WhenActionBeltUIDrop);
        }

        private void WhenActionBeltUIDrop(ActionBeltUIDropEvent e)
        {
            if (!actionBeltManager.IsOperational) return;

            center.BlinkBorderDropped();
            if (local.gameObject.activeSelf) local.BlinkBorderDropped();
        }
        
        private IEnumerator UpdateContentNextFrame()
        {
            yield return null;
            UpdateTheme();
            UpdateContent();
        }
        
        public void BeforeOpen()
        {
            StartCoroutine(UpdateContentNextFrame());
        }
        
        private void WhenActionBeltNextRight(ActionBeltUIToRightEvent e)
        {
            if (!actionBeltManager.IsOperational) return;
            if (!IsOptionActive) return;
            SwitchRight();
            contentIconAnimation.SpriteAnimation.Reset();
            StartCoroutine(UpdateContentNextFrame());
        }

        private void WhenActionBeltNextLeft(ActionBeltUIToLeftEvent e)
        {
            if (!actionBeltManager.IsOperational) return;
            if (!IsOptionActive) return;
            SwitchLeft();
            contentIconAnimation.SpriteAnimation.Reset();
            StartCoroutine(UpdateContentNextFrame());
        }
        
        private void WhenActionBeltUITakeAction(ActionBeltUITakeActionEvent e)
        {
            if (!actionBeltManager.IsOperational) return;
            
            center.BlinkBorderActionTaken();
            if (local.gameObject.activeSelf) local.BlinkBorderActionTaken();
        }

        private void UpdateContent()
        {
            var focus = GetFocus();
            contentIconAnimation.SpriteAnimation.ChangeAnimation(MapActionCategoryRUNNING(focus.ActionCategory));
            actionTextMeshPro.text = Proxy.Instance.I18N.Localise(focus.ActionLocalization);
            if (focus.DescriptionLocalization.IsNull())
            {
                local.gameObject.SetActive(false);    
            }
            else
            {
                local.gameObject.SetActive(true);
                var message = Proxy.Instance.I18N.Localise(focus.DescriptionLocalization, focus.DescriptionParams);
                localNewsTicker.Operational(message);
            }
        }
        
        private void Update()
        {
            UpdateTheme();
            
            if (!actionBeltManager.IsOperational)
            {
                Proxy.Instance.EventBus.Raise(new ActionBeltUICloseEvent());
                return;
            }
            
            switch (GetNumberOfActionsInBelt())
            {
                case 0:
                    Proxy.Instance.EventBus.Raise(new ActionBeltUICloseEvent());
                    return;
                case 1:
                    left.gameObject.SetActive(false);
                    right.gameObject.SetActive(false);
                    break;
                case > 1:
                    left.gameObject.SetActive(true);
                    right.gameObject.SetActive(true);
                    rightIconAnimation.SpriteAnimation.ChangeAnimation(MapActionCategoryIDLE(SneakPeekRight().ActionCategory));
                    leftIconAnimation.SpriteAnimation.ChangeAnimation(MapActionCategoryIDLE(SneakPeekLeft().ActionCategory));
                    break;
            }
        }

        private static string MapActionCategoryIDLE(ActionCategory actionCategory)
        {
            return actionCategory switch
            {
                ActionCategory.General => "General IDLE",
                ActionCategory.Terminal => "Terminal IDLE",
                _ => throw new ArgumentOutOfRangeException(nameof(actionCategory), actionCategory, null)
            };
        }
        
        private static string MapActionCategoryRUNNING(ActionCategory actionCategory)
        {
            return actionCategory switch
            {
                ActionCategory.General => "General RUNNING",
                ActionCategory.Terminal => "Terminal RUNNING",
                _ => throw new ArgumentOutOfRangeException(nameof(actionCategory), actionCategory, null)
            };
        }

        [GroupDebug, Button]
        private void SwitchLeft()
        {
            left.Righty();
            right.Lefty();
            center.BlinkBorderSelected();
            if (local.gameObject.activeSelf) local.BlinkBorderSelected();
        }
        
        [GroupDebug, Button]
        private void SwitchRight()
        {
            left.Righty();
            right.Lefty();
            center.BlinkBorderSelected();
            if (local.gameObject.activeSelf) local.BlinkBorderSelected();
        }
    }
}