using Dalamud.Interface;
using HSUI.Config;
using HSUI.Config.Attributes;
using HSUI.Enums;
using HSUI.Helpers;
using HSUI.Interface.Bars;
using HSUI.Interface.GeneralElements;
using Dalamud.Bindings.ImGui;
using Lumina.Excel;
using Lumina.Excel.Sheets;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;

namespace HSUI.Interface.StatusEffects
{
    [Section("Buffs and Debuffs")]
    [SubSection("Player Buffs", 0)]
    public class PlayerBuffsListConfig : UnitFrameStatusEffectsListConfig
    {
        public new static PlayerBuffsListConfig DefaultConfig()
        {
            var screenSize = ImGui.GetMainViewport().Size;
            var pos = new Vector2(screenSize.X * 0.38f, -screenSize.Y * 0.45f);
            var iconConfig = new StatusEffectIconConfig();
            iconConfig.DispellableBorderConfig.Enabled = false;

            return new PlayerBuffsListConfig(pos, HUDConstants.DefaultStatusEffectsListSize, true, false, true, GrowthDirections.Left | GrowthDirections.Down, iconConfig);
        }

        public PlayerBuffsListConfig(Vector2 position, Vector2 size, bool showBuffs, bool showDebuffs, bool showPermanentEffects,
            GrowthDirections growthDirections, StatusEffectIconConfig iconConfig)
            : base(position, size, showBuffs, showDebuffs, showPermanentEffects, growthDirections, iconConfig)
        {
        }
    }

    [Section("Buffs and Debuffs")]
    [SubSection("Player Debuffs", 0)]
    public class PlayerDebuffsListConfig : UnitFrameStatusEffectsListConfig
    {
        public new static PlayerDebuffsListConfig DefaultConfig()
        {
            var screenSize = ImGui.GetMainViewport().Size;
            var pos = new Vector2(screenSize.X * 0.38f, -screenSize.Y * 0.45f + HUDConstants.DefaultStatusEffectsListSize.Y);
            var iconConfig = new StatusEffectIconConfig();

            return new PlayerDebuffsListConfig(pos, HUDConstants.DefaultStatusEffectsListSize, false, true, true, GrowthDirections.Left | GrowthDirections.Down, iconConfig);
        }

        public PlayerDebuffsListConfig(Vector2 position, Vector2 size, bool showBuffs, bool showDebuffs, bool showPermanentEffects,
            GrowthDirections growthDirections, StatusEffectIconConfig iconConfig)
            : base(position, size, showBuffs, showDebuffs, showPermanentEffects, growthDirections, iconConfig)
        {
        }
    }

    [Section("Buffs and Debuffs")]
    [SubSection("Target Buffs", 0)]
    public class TargetBuffsListConfig : UnitFrameStatusEffectsListConfig
    {
        public new static TargetBuffsListConfig DefaultConfig()
        {
            var pos = new Vector2(0, -1);
            var iconConfig = new StatusEffectIconConfig();
            iconConfig.DispellableBorderConfig.Enabled = false;

            var config = new TargetBuffsListConfig(pos, HUDConstants.DefaultStatusEffectsListSize, true, false, true, GrowthDirections.Right | GrowthDirections.Up, iconConfig);
            config.AnchorToUnitFrame = true;
            config.UnitFrameAnchor = DrawAnchor.TopLeft;

            return config;
        }

        public TargetBuffsListConfig(Vector2 position, Vector2 size, bool showBuffs, bool showDebuffs, bool showPermanentEffects,
            GrowthDirections growthDirections, StatusEffectIconConfig iconConfig)
            : base(position, size, showBuffs, showDebuffs, showPermanentEffects, growthDirections, iconConfig)
        {
        }
    }

    [Section("Buffs and Debuffs")]
    [SubSection("Target Debuffs", 0)]
    public class TargetDebuffsListConfig : UnitFrameStatusEffectsListConfig
    {
        public new static TargetDebuffsListConfig DefaultConfig()
        {
            var pos = new Vector2(0, -85);
            var iconConfig = new StatusEffectIconConfig();
            iconConfig.DispellableBorderConfig.Enabled = false;

            var config = new TargetDebuffsListConfig(pos, HUDConstants.DefaultStatusEffectsListSize, false, true, true, GrowthDirections.Right | GrowthDirections.Up, iconConfig);
            config.AnchorToUnitFrame = true;
            config.UnitFrameAnchor = DrawAnchor.TopLeft;

            return config;
        }

        public TargetDebuffsListConfig(Vector2 position, Vector2 size, bool showBuffs, bool showDebuffs, bool showPermanentEffects,
            GrowthDirections growthDirections, StatusEffectIconConfig iconConfig)
            : base(position, size, showBuffs, showDebuffs, showPermanentEffects, growthDirections, iconConfig)
        {
        }
    }

    [Section("Buffs and Debuffs")]
    [SubSection("Focus Target Buffs", 0)]
    public class FocusTargetBuffsListConfig : UnitFrameStatusEffectsListConfig
    {
        public new static FocusTargetBuffsListConfig DefaultConfig()
        {
            var pos = new Vector2(0, -1);
            var iconConfig = new StatusEffectIconConfig();
            iconConfig.DispellableBorderConfig.Enabled = false;

            var config = new FocusTargetBuffsListConfig(pos, HUDConstants.DefaultStatusEffectsListSize, true, false, true, GrowthDirections.Right | GrowthDirections.Up, iconConfig);
            config.AnchorToUnitFrame = true;
            config.UnitFrameAnchor = DrawAnchor.TopLeft;

            return config;
        }

        public FocusTargetBuffsListConfig(Vector2 position, Vector2 size, bool showBuffs, bool showDebuffs, bool showPermanentEffects,
            GrowthDirections growthDirections, StatusEffectIconConfig iconConfig)
            : base(position, size, showBuffs, showDebuffs, showPermanentEffects, growthDirections, iconConfig)
        {
        }
    }

    [Section("Buffs and Debuffs")]
    [SubSection("Focus Target Debuffs", 0)]
    public class FocusTargetDebuffsListConfig : UnitFrameStatusEffectsListConfig
    {
        public new static FocusTargetDebuffsListConfig DefaultConfig()
        {
            var pos = new Vector2(0, -85);
            var iconConfig = new StatusEffectIconConfig();
            iconConfig.DispellableBorderConfig.Enabled = false;

            var config = new FocusTargetDebuffsListConfig(pos, HUDConstants.DefaultStatusEffectsListSize, false, true, true, GrowthDirections.Right | GrowthDirections.Up, iconConfig);
            config.AnchorToUnitFrame = true;
            config.UnitFrameAnchor = DrawAnchor.TopLeft;

            return config;
        }

        public FocusTargetDebuffsListConfig(Vector2 position, Vector2 size, bool showBuffs, bool showDebuffs, bool showPermanentEffects,
            GrowthDirections growthDirections, StatusEffectIconConfig iconConfig)
            : base(position, size, showBuffs, showDebuffs, showPermanentEffects, growthDirections, iconConfig)
        {
        }
    }

    public abstract class UnitFrameStatusEffectsListConfig : StatusEffectsListConfig
    {
        [Checkbox("Anchor to Unit Frame")]
        [Order(16)]
        public bool AnchorToUnitFrame = false;

        [Anchor("Unit Frame Anchor")]
        [Order(17, collapseWith = nameof(AnchorToUnitFrame))]
        public DrawAnchor UnitFrameAnchor = DrawAnchor.TopLeft;

        [NestedConfig("Visibility", 200)]
        public VisibilityConfig VisibilityConfig = new VisibilityConfig();

        public UnitFrameStatusEffectsListConfig(Vector2 position, Vector2 size, bool showBuffs, bool showDebuffs, bool showPermanentEffects,
            GrowthDirections growthDirections, StatusEffectIconConfig iconConfig)
            : base(position, size, showBuffs, showDebuffs, showPermanentEffects, growthDirections, iconConfig)
        {
        }
    }

    public class StatusEffectsListConfig : MovablePluginConfigObject
    {
        public bool ShowBuffs;
        public bool ShowDebuffs;

        [DragInt2("Size", min = 1, max = 4000)]
        [Order(15)]
        public Vector2 Size;

        [DragInt2("Icon Padding", min = 0, max = 500)]
        [Order(19)]
        public Vector2 IconPadding = new(2, 2);

        [Checkbox("Preview", isMonitored = true)]
        [Order(20)]
        public bool Preview;

        [Checkbox("Fill Rows First", spacing = true)]
        [Order(25)]
        public bool FillRowsFirst = true;

        [Combo("Icons Growth Direction",
            "Right and Down",
            "Right and Up",
            "Left and Down",
            "Left and Up",
            "Centered and Up",
            "Centered and Down",
            "Centered and Left",
            "Centered and Right"
        )]
        [Order(30)]
        public int Directions;

        [DragInt("Limit (-1 for no limit)", min = -1, max = 1000)]
        [Order(35)]
        public int Limit = -1;

        [Checkbox("Permanent Effects", spacing = true)]
        [Order(40)]
        public bool ShowPermanentEffects;

        [Checkbox("Permanent Effects First")]
        [Order(41)]
        public bool ShowPermanentFirst;

        [Checkbox("Only My Effects", spacing = true)]
        [Order(42)]
        public bool ShowOnlyMine = false;

        [Checkbox("My Effects First")]
        [Order(43)]
        public bool ShowMineFirst = false;

        [Checkbox("Pet As Own Effect")]
        [Order(44)]
        public bool IncludePetAsOwn = false;

        [Checkbox("Sort by Duration", spacing = true, help = "If enabled, \"Permanent Effects First\" and \"My Effects First\" will be ignored!")]
        [Order(45)]
        public bool SortByDuration = false;

        [RadioSelector("Ascending", "Descending")]
        [Order(46, collapseWith = nameof(SortByDuration))]
        public StatusEffectDurationSortType DurationSortType = StatusEffectDurationSortType.Ascending;

        [Checkbox("Tooltips", spacing = true)]
        [Order(47)]
        public bool ShowTooltips = true;

        [Checkbox("Disable Interaction", help = "Enabling this will disable right clicking buffs off, or the shortcut to blacklist/whitelist a status effect.")]
        [Order(48)]
        public bool DisableInteraction = false;

        [Checkbox("Hide when Dead")]
        [Order(49)]
        public bool HideWhenDead = true;

        [NestedConfig("Icons", 65)]
        public StatusEffectIconConfig IconConfig;

        [NestedConfig("Filter Status Effects", 70, separator = true, spacing = false, collapsingHeader = false)]
        public StatusEffectsBlacklistConfig BlacklistConfig = new StatusEffectsBlacklistConfig();


        public StatusEffectsListConfig(Vector2 position, Vector2 size, bool showBuffs, bool showDebuffs, bool showPermanentEffects,
                                       GrowthDirections growthDirections, StatusEffectIconConfig iconConfig)
        {
            Position = position;
            Size = size;
            ShowBuffs = showBuffs;
            ShowDebuffs = showDebuffs;
            ShowPermanentEffects = showPermanentEffects;

            SetGrowthDirections(growthDirections);

            IconConfig = iconConfig;

            Strata = StrataLevel.HIGH;
        }

        private void SetGrowthDirections(GrowthDirections growthDirections)
        {
            Directions = LayoutHelper.IndexFromGrowthDirections(growthDirections);
        }
    }

    [Exportable(false)]
    [Disableable(false)]
    public class StatusEffectIconConfig : PluginConfigObject
    {
        [DragInt2("Icon Size", min = 1, max = 1000)]
        [Order(5)]
        public Vector2 Size = new(40, 40);

        [Checkbox("Crop Icon", spacing = true)]
        [Order(20)]
        public bool CropIcon = true;

        [NestedConfig("Border", 25, collapseWith = nameof(CropIcon), collapsingHeader = false)]
        public StatusEffectIconBorderConfig BorderConfig = new();

        [NestedConfig("Shadow", 26, collapseWith = nameof(CropIcon), collapsingHeader = false)]
        public ShadowConfig ShadowConfig = new ShadowConfig() { Enabled = false };

        [NestedConfig("Dispellable Effects Border", 30, collapseWith = nameof(CropIcon), collapsingHeader = false)]
        public StatusEffectIconBorderConfig DispellableBorderConfig = new(new PluginConfigColor(new Vector4(141f / 255f, 206f / 255f, 229f / 255f, 100f / 100f)), 2);

        [NestedConfig("My Effects Border", 35, collapseWith = nameof(CropIcon), collapsingHeader = false)]
        public StatusEffectIconBorderConfig OwnedBorderConfig = new(new PluginConfigColor(new Vector4(35f / 255f, 179f / 255f, 69f / 255f, 100f / 100f)), 1);

        [NestedConfig("Duration", 50)]
        public LabelConfig DurationLabelConfig;

        [NestedConfig("Stacks", 60)]
        public LabelConfig StacksLabelConfig;

        public StatusEffectIconConfig(LabelConfig? durationLabelConfig = null, LabelConfig? stacksLabelConfig = null)
        {
            DurationLabelConfig = durationLabelConfig ?? StatusEffectsListsDefaults.DefaultDurationLabelConfig();
            StacksLabelConfig = stacksLabelConfig ?? StatusEffectsListsDefaults.DefaultStacksLabelConfig();
        }
    }

    [Exportable(false)]
    public class StatusEffectIconBorderConfig : PluginConfigObject
    {
        [ColorEdit4("Color")]
        [Order(5)]
        public PluginConfigColor Color = new(Vector4.UnitW);

        [DragInt("Thickness", min = 1, max = 100)]
        [Order(10)]
        public int Thickness = 1;

        public StatusEffectIconBorderConfig()
        {
        }

        public StatusEffectIconBorderConfig(PluginConfigColor color, int thickness)
        {
            Color = color;
            Thickness = thickness;
        }
    }

    internal class StatusEffectsListsDefaults
    {
        internal static LabelConfig DefaultDurationLabelConfig()
        {
            return new LabelConfig(Vector2.Zero, "", DrawAnchor.Center, DrawAnchor.Center);
        }

        internal static LabelConfig DefaultStacksLabelConfig()
        {
            var config = new LabelConfig(new Vector2(16, -11), "", DrawAnchor.Center, DrawAnchor.Center);
            config.Color = new(Vector4.UnitW);
            config.OutlineColor = new(Vector4.One);
            config.ShadowConfig.Color = new(Vector4.One);

            return config;
        }
    }

    public enum FilterType
    {
        Blacklist,
        Whitelist
    }

    [Exportable(false)]
    public class StatusEffectsBlacklistConfig : PluginConfigObject
    {
        [RadioSelector(typeof(FilterType))]
        [Order(5)]
        public FilterType FilterType;

        public SortedList<string, uint> List = new SortedList<string, uint>();

        [JsonIgnore] private string? _errorMessage = null;
        [JsonIgnore] private string? _importString = null;
        [JsonIgnore] private bool _clearingList = false;

        private string KeyName(Status status)
        {
            return $"{status.Name}[{status.RowId.ToString()}]";
        }

        public bool StatusAllowed(Status status)
        {
            bool inList = List.Any(pair => pair.Value == status.RowId);
            if ((inList && FilterType == FilterType.Blacklist) || (!inList && FilterType == FilterType.Whitelist))
            {
                return false;
            }

            return true;
        }

        public bool AddNewEntry(Status? status)
        {
            if (status != null && status.HasValue && !List.ContainsKey(KeyName(status.Value)))
            {
                List.Add(KeyName(status.Value), status.Value.RowId);
                _input = "";

                return true;
            }

            return false;
        }

        private bool AddNewEntry(string input, ExcelSheet<Status>? sheet)
        {
            if (input.Length > 0 && sheet != null)
            {
                List<Status> statusToAdd = new List<Status>();

                // try id
                if (uint.TryParse(input, out uint uintValue))
                {
                    if (uintValue > 0)
                    {
                        Status? status = sheet.GetRow(uintValue);
                        if (status != null && status.HasValue)
                        {
                            statusToAdd.Add(status.Value);
                        }
                    }
                }

                // try name
                if (statusToAdd.Count == 0)
                {
                    var enumerator = sheet.GetEnumerator();

                    while (enumerator.MoveNext())
                    {
                        Status item = enumerator.Current;
                        if (item.Name.ToString().ToLower() == input.ToLower())
                        {
                            statusToAdd.Add(item);
                        }
                    }
                }

                bool added = false;
                foreach (Status status in statusToAdd)
                {
                    added |= AddNewEntry(status);
                }
                return added;
            }

            return false;
        }

        private string ExportList()
        {
            string exportString = "";

            for (int i = 0; i < List.Keys.Count; i++)
            {
                exportString += List.Keys[i] + "|";
                exportString += List.Values[i] + "|";
            }

            return exportString;
        }

        private string? ImportList(string importString)
        {
            SortedList<string, uint> tmpList = new SortedList<string, uint>();

            try
            {
                string[] strings = importString.Trim().Split("|", StringSplitOptions.RemoveEmptyEntries);
                for (int i = 0; i < strings.Length; i += 2)
                {
                    if (i + 1 >= strings.Length)
                    {
                        break;
                    }

                    string key = strings[i];
                    uint value = uint.Parse(strings[i + 1]);

                    tmpList.Add(key, value);
                }
            }
            catch
            {
                return "Error importing list!";
            }

            List = tmpList;
            return null;
        }

        [JsonIgnore]
        private string _input = "";

        [ManualDraw]
        public bool Draw(ref bool changed)
        {
            if (!Enabled)
            {
                return false;
            }

            var flags =
                ImGuiTableFlags.RowBg |
                ImGuiTableFlags.Borders |
                ImGuiTableFlags.BordersOuter |
                ImGuiTableFlags.BordersInner |
                ImGuiTableFlags.ScrollY |
                ImGuiTableFlags.SizingFixedSame;

            var sheet = Plugin.DataManager.GetExcelSheet<Status>();
            var iconSize = new Vector2(30, 30);
            var indexToRemove = -1;

            if (ImGui.BeginChild("Filter Effects", new Vector2(0, 360), false, ImGuiWindowFlags.NoSavedSettings | ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoScrollWithMouse))
            {
                ImGui.Text("    ");
                ImGui.SameLine();
                ImGui.Text("Type an ID or Name");

                ImGui.Text("    ");
                ImGui.SameLine();
                ImGui.PushItemWidth(300);
                if (ImGui.InputText("", ref _input, 64, ImGuiInputTextFlags.EnterReturnsTrue))
                {
                    changed |= AddNewEntry(_input, sheet);
                    ImGui.SetKeyboardFocusHere(-1);
                }

                // add
                ImGui.SameLine();
                ImGui.PushFont(UiBuilder.IconFont);
                if (ImGui.Button(FontAwesomeIcon.Plus.ToIconString(), new Vector2(0, 0)))
                {
                    changed |= AddNewEntry(_input, sheet);
                    ImGui.SetKeyboardFocusHere(-2);
                }

                // export
                ImGui.SameLine();
                ImGui.SetCursorPosX(ImGui.GetCursorPosX() + 154);
                if (ImGui.Button(FontAwesomeIcon.Upload.ToIconString(), new Vector2(0, 0)))
                {
                    ImGui.SetClipboardText(ExportList());
                    ImGui.OpenPopup("export_succes_popup");
                }
                ImGui.PopFont();
                ImGuiHelper.SetTooltip("Export List to Clipboard");

                // export success popup
                if (ImGui.BeginPopup("export_succes_popup"))
                {
                    ImGui.Text("List exported to clipboard!");
                    ImGui.EndPopup();
                }

                // import
                ImGui.SameLine();
                ImGui.PushFont(UiBuilder.IconFont);
                if (ImGui.Button(FontAwesomeIcon.Download.ToIconString(), new Vector2(0, 0)))
                {
                    _importString = ImGui.GetClipboardText();
                }
                ImGui.PopFont();
                ImGuiHelper.SetTooltip("Import List from Clipboard");

                // clear
                ImGui.SameLine();
                ImGui.PushFont(UiBuilder.IconFont);
                if (ImGui.Button(FontAwesomeIcon.Trash.ToIconString(), new Vector2(0, 0)))
                {
                    _clearingList = true;
                }
                ImGui.PopFont();
                ImGuiHelper.SetTooltip("Clear List");

                ImGui.Text("    ");
                ImGui.SameLine();

                if (ImGui.BeginTable("table", 4, flags, new Vector2(583, List.Count > 0 ? 200 : 40)))
                {
                    ImGui.TableSetupColumn("Icon", ImGuiTableColumnFlags.WidthFixed, 0, 0);
                    ImGui.TableSetupColumn("ID", ImGuiTableColumnFlags.WidthFixed, 0, 1);
                    ImGui.TableSetupColumn("Name", ImGuiTableColumnFlags.WidthStretch, 0, 2);
                    ImGui.TableSetupColumn("", ImGuiTableColumnFlags.WidthFixed, 0, 3);

                    ImGui.TableSetupScrollFreeze(0, 1);
                    ImGui.TableHeadersRow();

                    for (int i = 0; i < List.Count; i++)
                    {
                        var id = List.Values[i];
                        var name = List.Keys[i];
                        var row = sheet?.GetRow(id);

                        if (_input != "" && !name.ToUpper().Contains(_input.ToUpper()))
                        {
                            continue;
                        }

                        ImGui.PushID(i.ToString());
                        ImGui.TableNextRow(ImGuiTableRowFlags.None, iconSize.Y);

                        // icon
                        if (ImGui.TableSetColumnIndex(0))
                        {
                            if (row != null)
                            {
                                DrawHelper.DrawIcon<Status>(row, ImGui.GetCursorPos(), iconSize, false, true);
                            }
                        }

                        // id
                        if (ImGui.TableSetColumnIndex(1))
                        {
                            ImGui.Text(id.ToString());
                        }

                        // name
                        if (ImGui.TableSetColumnIndex(2))
                        {
                            ImGui.Text(row != null && row.HasValue ? row.Value.Name.ToString() : name);
                        }

                        // remove
                        if (ImGui.TableSetColumnIndex(3))
                        {
                            ImGui.PushFont(UiBuilder.IconFont);
                            ImGui.PushStyleColor(ImGuiCol.Button, Vector4.Zero);
                            ImGui.PushStyleColor(ImGuiCol.ButtonActive, Vector4.Zero);
                            ImGui.PushStyleColor(ImGuiCol.ButtonHovered, Vector4.Zero);
                            if (ImGui.Button(FontAwesomeIcon.Trash.ToIconString(), iconSize))
                            {
                                changed = true;
                                indexToRemove = i;
                            }
                            ImGui.PopFont();
                            ImGui.PopStyleColor(3);
                        }
                        ImGui.PopID();
                    }

                    ImGui.EndTable();
                }
                ImGui.Text("    ");
                ImGui.SameLine();
                ImGui.Text("Tip: You can [Ctrl + Alt + Shift] + Left Click on a status effect to automatically add it to the list.");

            }

            if (indexToRemove >= 0)
            {
                List.RemoveAt(indexToRemove);
            }

            ImGui.EndChild();

            // error message
            if (_errorMessage != null)
            {
                if (ImGuiHelper.DrawErrorModal(_errorMessage))
                {
                    _errorMessage = null;
                }
            }

            // import confirmation
            if (_importString != null)
            {
                string[] message = new string[] {
                    "All the elements in the list will be replaced.",
                    "Are you sure you want to import?"
                };
                var (didConfirm, didClose) = ImGuiHelper.DrawConfirmationModal("Import?", message);

                if (didConfirm)
                {
                    _errorMessage = ImportList(_importString);
                    changed = true;
                }

                if (didConfirm || didClose)
                {
                    _importString = null;
                }
            }

            // clear confirmation
            if (_clearingList)
            {
                string message = "Are you sure you want to clear the list?";

                var (didConfirm, didClose) = ImGuiHelper.DrawConfirmationModal("Clear List?", message);

                if (didConfirm)
                {
                    List.Clear();
                    changed = true;
                }

                if (didConfirm || didClose)
                {
                    _clearingList = false;
                }
            }

            return false;
        }
    }


    public class StatusEffectsBlacklistConfigConverter : PluginConfigObjectConverter
    {
        public StatusEffectsBlacklistConfigConverter()
        {
            NewTypeFieldConverter<bool, FilterType> converter;
            converter = new NewTypeFieldConverter<bool, FilterType>("FilterType", FilterType.Blacklist, (oldValue) =>
            {
                return oldValue ? FilterType.Whitelist : FilterType.Blacklist;
            });

            FieldConvertersMap.Add("UseAsWhitelist", converter);
        }

        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(StatusEffectsBlacklistConfig);
        }
    }

    [Section("Buffs and Debuffs")]
    [SubSection("Custom Effects", 0)]
    public class CustomEffectsListConfig : StatusEffectsListConfig
    {
        public new static CustomEffectsListConfig DefaultConfig()
        {
            var iconConfig = new StatusEffectIconConfig();
            iconConfig.DispellableBorderConfig.Enabled = false;
            iconConfig.Size = new Vector2(30, 30);

            var pos = new Vector2(0, HUDConstants.BaseHUDOffsetY);
            var size = new Vector2(250, iconConfig.Size.Y * 3 + 10);

            var config = new CustomEffectsListConfig(pos, size, true, true, false, GrowthDirections.Centered | GrowthDirections.Up, iconConfig);
            config.Enabled = false;
            config.Directions = 5;

            // pre-populated white list
            config.BlacklistConfig.FilterType = FilterType.Whitelist;

            ExcelSheet<Status>? sheet = Plugin.DataManager.GetExcelSheet<Status>();
            if (sheet != null)
            {
                // Left Eye
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(1184));
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(1454));

                // Battle Litany
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(786));
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(1414));

                // Brotherhood
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(1185));
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(2174));

                // Battle Voice
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(141));

                // Devilment
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(1825));

                // Technical Finish
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(1822));
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(2050));

                // Standard Finish
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(1821));
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(2024));
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(2105));
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(2113));

                // Embolden
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(1239));
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(1297));
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(2282));

                // Devotion
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(1213));

                // Divination
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(1878));
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(2034));

                // Chain Stratagem
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(1221));
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(1406));

                // Radiant Finale
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(2722));
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(2964));

                // Arcane Circle
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(2599));

                // Searing Light
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(2703));

                // Trick Attack
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(638));

                // ------ AST Card Buffs -------
                // The Balance
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(829));
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(1338));
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(1882));

                // The Bole
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(830));
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(1339));
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(1883));

                // The Arrow
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(831));
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(1884));

                // The Spear
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(832));
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(1885));

                // The Ewer
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(833));
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(1340));
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(1886));

                // The Spire
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(834));
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(1341));
                config.BlacklistConfig.AddNewEntry(sheet.GetRow(1887));
            }

            return config;
        }

        public CustomEffectsListConfig(Vector2 position, Vector2 size, bool showBuffs, bool showDebuffs, bool showPermanentEffects,
            GrowthDirections growthDirections, StatusEffectIconConfig iconConfig)
            : base(position, size, showBuffs, showDebuffs, showPermanentEffects, growthDirections, iconConfig)
        {
        }
    }

    public enum StatusEffectDurationSortType
    {
        Ascending,
        Descending
    }
}