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

namespace Intrepid.Gameplay.Entities.Player.ActionBelt.UI
{
    public class ActionBeltUI : EventListener
    {
        [GroupInjections, SerializeField] private Window.Window actionBeltWindow;
        [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 Func<ActionEnvelope> GetFocus { get; set; }
        public Func<ActionEnvelope> SneakPeekRight { get; set; }
        public Func<ActionEnvelope> SneakPeekLeft { get; set; }
        private Func<int> GetNumberOfActionsInBelt { get; set; } = () => 0;
        private bool IsOptionActive { get; set; }
        
        protected override void InitializeVariables()
        {
        }

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

        private void UpdateTheme()
        {
            var theme = ThemeManager.Instance.CurrentTheme.ActionBeltTheme;
            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<ActionBeltUIOpenEvent>(WhenActionBeltUIOpen);
            Subscribe<ActionBeltUICloseEvent>(WhenActionBeltUIClose);
            
            Subscribe<ActionBeltUIToRightEvent>(WhenActionBeltNextRight);
            Subscribe<ActionBeltUIToLeftEvent>(WhenActionBeltNextLeft);
            
            Subscribe<ActionBeltUITakeActionEvent>(WhenActionBeltUITakeAction);
            Subscribe<ActionBeltUIDropEvent>(WhenActionBeltUIDrop);
        }

        private void WhenActionBeltUIDrop(ActionBeltUIDropEvent e)
        {
            center.BlinkBorderDropped();
            if (local.gameObject.activeSelf) local.BlinkBorderDropped();
        }

        private void WhenActionBeltUIOpen(ActionBeltUIOpenEvent e)
        {
            if (GetFocus is not null) return;
            GetFocus = e.GetFocusActionEnvelope;
            SneakPeekRight = e.SneakPeekRightActionEnvelope;
            SneakPeekLeft = e.SneakPeekLeftActionEnvelope;
            GetNumberOfActionsInBelt = e.GetSize;
            IsOptionActive = GetNumberOfActionsInBelt() > 1;
            actionBeltWindow.Open();
            UpdateContent();
        }

        private void WhenActionBeltUIClose(ActionBeltUICloseEvent e)
        {
            Close();
        }
        
        private void WhenActionBeltNextRight(ActionBeltUIToRightEvent e)
        {
            if (!IsOptionActive) return;
            SwitchRight();
            contentIconAnimation.SpriteAnimation.Reset();
            UpdateContent();
        }

        private void WhenActionBeltNextLeft(ActionBeltUIToLeftEvent e)
        {
            if (!IsOptionActive) return;
            SwitchLeft();
            contentIconAnimation.SpriteAnimation.Reset();
            UpdateContent();
        }
        
        private void WhenActionBeltUITakeAction(ActionBeltUITakeActionEvent e)
        {
            center.BlinkBorderActionTaken();
            if (local.gameObject.activeSelf) local.BlinkBorderActionTaken();
        }
        
        private void Close()
        {
            if (GetFocus is null) return;
            IsOptionActive = false;
            GetFocus = null;
            SneakPeekRight = null;
            SneakPeekLeft = null;
            GetNumberOfActionsInBelt = () => 0;
            actionBeltWindow.Close();
        }

        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();
            switch (GetNumberOfActionsInBelt())
            {
                case 0:
                    Close();
                    IsOptionActive = false;
                    return;
                case 1:
                    left.gameObject.SetActive(false);
                    right.gameObject.SetActive(false);
                    IsOptionActive = false;
                    break;
                case > 1:
                    left.gameObject.SetActive(true);
                    right.gameObject.SetActive(true);
                    IsOptionActive = 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();
        }
    }
}