using System;
using Intrepid.Diagnostics;
using Intrepid.Localization;
using Intrepid.TagSystem;
using Intrepid.Utilities;
using Sirenix.OdinInspector;
using UnityEngine;

namespace Intrepid.Gameplay.Codex.Visual
{
    [Serializable]
    [CreateAssetMenu(fileName = "New Pictorial Protocol Tag", menuName = "GON/CODEX/Visual/Pictorial Protocol Tag")]
    public class PictorialProtocolTag : Tag
    {
        [GroupInjections, SerializeField] private LocalizationTag localization;
        [GroupInjections, SerializeField] private LocalizationTag description;
        [SerializeField, HideLabel, Title("Interface Style")] private PictorialProtocolInterfaceStyle interfaceStyle;
        
        public LocalizationTag Localization => localization;
        public LocalizationTag Description => description;
        public PictorialProtocolInterfaceStyle InterfaceStyle => interfaceStyle;
        
        // katakana
        // kanji
        
        public Color GetSurfaceColor(PictorialSurfaceType surfaceType)
        {
            return surfaceType switch
            {
                PictorialSurfaceType.Base => InterfaceStyle.SurfaceBase,
                PictorialSurfaceType.Raised => InterfaceStyle.SurfaceRaised,
                PictorialSurfaceType.Deep => InterfaceStyle.SurfaceDeep,
                PictorialSurfaceType.Overlay => InterfaceStyle.SurfaceOverlay,
                _ => throw new ArgumentOutOfRangeException(nameof(surfaceType), surfaceType, null)
            };
        }

        public Color GetTextColor(PictorialTextType textType)
        {
            return textType switch
            {
                PictorialTextType.Primary => InterfaceStyle.TextPrimary,
                PictorialTextType.Secondary => InterfaceStyle.TextSecondary,
                PictorialTextType.Muted => InterfaceStyle.TextMuted,
                PictorialTextType.Disabled => InterfaceStyle.TextDisabled,
                _ => throw new ArgumentOutOfRangeException(nameof(textType), textType, null)
            };
        }

        public Color GetSignalColor(PictorialSignalType signalType)
        {
            return signalType switch
            {
                PictorialSignalType.Primary => InterfaceStyle.SignalPrimary,
                PictorialSignalType.Secondary => InterfaceStyle.SignalSecondary,
                PictorialSignalType.Focus => InterfaceStyle.SignalFocus,
                PictorialSignalType.Selected => InterfaceStyle.SignalSelected,
                PictorialSignalType.Disabled => InterfaceStyle.SignalDisabled,
                PictorialSignalType.Denied => InterfaceStyle.SignalDenied,
                PictorialSignalType.Warning => InterfaceStyle.SignalWarning,
                PictorialSignalType.Corruption => InterfaceStyle.SignalCorruption,
                _ => throw new ArgumentOutOfRangeException(nameof(signalType), signalType, null)
            };
        }

        public Color GetGaugeColor(PictorialGaugeType gaugeType)
        {
            return gaugeType switch
            {
                PictorialGaugeType.Life => InterfaceStyle.GaugeLife,
                PictorialGaugeType.Shield => InterfaceStyle.GaugeShield,
                PictorialGaugeType.Cadence => InterfaceStyle.GaugeCadence,
                PictorialGaugeType.Progress => InterfaceStyle.GaugeProgress,
                _ => throw new ArgumentOutOfRangeException(nameof(gaugeType), gaugeType, null)
            };
        }

        public Color GetLineColor(PictorialLineType lineType)
        {
            return lineType switch
            {
                PictorialLineType.Subtle => InterfaceStyle.LineSubtle,
                PictorialLineType.Active => InterfaceStyle.LineActive,
                PictorialLineType.Critical => InterfaceStyle.LineCritical,
                _ => throw new ArgumentOutOfRangeException(nameof(lineType), lineType, null)
            };
        }
    }
    
    [Serializable]
    public class PictorialProtocolInterfaceStyle
    {
        [GroupConfigurations("Surfaces"), SerializeField] private Color surfaceBase = Color.black;
        [GroupConfigurations("Surfaces"), SerializeField] private Color surfaceRaised = Color.black;
        [GroupConfigurations("Surfaces"), SerializeField] private Color surfaceDeep = Color.black;
        [GroupConfigurations("Surfaces"), SerializeField] private Color surfaceOverlay = Color.black;

        [GroupConfigurations("Texts"), SerializeField] private Color textPrimary = Color.white;
        [GroupConfigurations("Texts"), SerializeField] private Color textSecondary = Color.gray;
        [GroupConfigurations("Texts"), SerializeField] private Color textMuted = Color.gray;
        [GroupConfigurations("Texts"), SerializeField] private Color textDisabled = Color.gray;

        [GroupConfigurations("Signals"), SerializeField] private Color signalPrimary = Color.cornflowerBlue;
        [GroupConfigurations("Signals"), SerializeField] private Color signalSecondary = Color.lightSeaGreen;
        [GroupConfigurations("Signals"), SerializeField] private Color signalFocus = Color.white;
        [GroupConfigurations("Signals"), SerializeField] private Color signalSelected = Color.yellow;
        [GroupConfigurations("Signals"), SerializeField] private Color signalDisabled = Color.gray;
        [GroupConfigurations("Signals"), SerializeField] private Color signalDenied = Color.darkRed;
        [GroupConfigurations("Signals"), SerializeField] private Color signalWarning = Color.orange;
        [GroupConfigurations("Signals"), SerializeField] private Color signalCorruption = Color.magenta;

        [GroupConfigurations("Gauges"), SerializeField] private Color gaugeLife = Color.red;
        [GroupConfigurations("Gauges"), SerializeField] private Color gaugeShield = Color.cyan;
        [GroupConfigurations("Gauges"), SerializeField] private Color gaugeCadence = Color.white;
        [GroupConfigurations("Gauges"), SerializeField] private Color gaugeProgress = Color.white;

        [GroupConfigurations("Lines"), SerializeField] private Color lineSubtle = Color.gray;
        [GroupConfigurations("Lines"), SerializeField] private Color lineActive = Color.white;
        [GroupConfigurations("Lines"), SerializeField] private Color lineCritical = Color.red;

        public Color SurfaceBase => surfaceBase;
        public Color SurfaceRaised => surfaceRaised;
        public Color SurfaceDeep => surfaceDeep;
        public Color SurfaceOverlay => surfaceOverlay;

        public Color TextPrimary => textPrimary;
        public Color TextSecondary => textSecondary;
        public Color TextMuted => textMuted;
        public Color TextDisabled => textDisabled;

        public Color SignalPrimary => signalPrimary;
        public Color SignalSecondary => signalSecondary;
        public Color SignalFocus => signalFocus;
        public Color SignalSelected => signalSelected;
        public Color SignalDisabled => signalDisabled;
        public Color SignalDenied => signalDenied;
        public Color SignalWarning => signalWarning;
        public Color SignalCorruption => signalCorruption;

        public Color GaugeLife => gaugeLife;
        public Color GaugeShield => gaugeShield;
        public Color GaugeCadence => gaugeCadence;
        public Color GaugeProgress => gaugeProgress;

        public Color LineSubtle => lineSubtle;
        public Color LineActive => lineActive;
        public Color LineCritical => lineCritical;

        private bool TryParseColor(string colorSchema, int nColors, out Color[] colors)
        {
            colors = null;
            if (string.IsNullOrWhiteSpace(colorSchema))
            {
                DLogger.LogWarn("Color Schema is empty.");
                return false;
            }
            var colorStrings = colorSchema.Split(',');
            if (colorStrings.Length < nColors)
            {
                DLogger.LogWarn($"Palette string must contain at least {nColors} hex colors.");
                return false;
            }

            colors = new Color[colorStrings.Length];
            for (var i = 0; i < colorStrings.Length; i++)
            {
                if (ColorUtility.TryParseHtmlString(colorStrings[i].Trim(), out var color))
                {
                    colors[i] = color;
                }
                else
                {
                    DLogger.LogWarn($"Invalid color code: {colorStrings[i]}");
                    return false;
                }
            }

            return true;
        }

        [GroupDebug, Button(ButtonSizes.Medium, ButtonStyle.FoldoutButton)]
        private void SetSurfaceColorSchema(string colorSchema)
        {
            if (TryParseColor(colorSchema, 4, out var colors))
            {
                surfaceBase = colors[0];
                surfaceRaised = colors[1];
                surfaceDeep = colors[2];
                surfaceOverlay = colors[3];
            }
        }
        
        [GroupDebug, Button(ButtonSizes.Medium, ButtonStyle.FoldoutButton)]
        private void SetTextColorSchema(string colorSchema)
        {
            if (TryParseColor(colorSchema, 4, out var colors))
            {
                textPrimary = colors[0];
                textSecondary = colors[1];
                textMuted = colors[2];
                textDisabled = colors[3];
            }
        }
        
        [GroupDebug, Button(ButtonSizes.Medium, ButtonStyle.FoldoutButton)]
        private void SetSignalsColorSchema(string colorSchema)
        {
            if (TryParseColor(colorSchema, 8, out var colors))
            {
                signalPrimary = colors[0];
                signalSecondary = colors[1];
                signalFocus = colors[2];
                signalSelected = colors[3];
                signalDisabled = colors[4];
                signalDenied = colors[5];
                signalWarning = colors[6];
                signalCorruption = colors[7];
            }
        }
        
        [GroupDebug, Button(ButtonSizes.Medium, ButtonStyle.FoldoutButton)]
        private void SetResourceColorSchema(string colorSchema)
        {
            if (TryParseColor(colorSchema, 4, out var colors))
            {
                gaugeLife = colors[0];
                gaugeShield = colors[1];
                gaugeCadence = colors[2];
                gaugeProgress = colors[3];
            }
        }
        
        [GroupDebug, Button(ButtonSizes.Medium, ButtonStyle.FoldoutButton)]
        private void SetLineColorSchema(string colorSchema)
        {
            if (TryParseColor(colorSchema, 3, out var colors))
            {
                lineSubtle = colors[0];
                lineActive = colors[1];
                lineCritical = colors[2];
            }
        }
    }
}