using HSUI.Config;
using HSUI.Config.Attributes;
using HSUI.Enums;
using HSUI.Helpers;
using HSUI.Interface.Bars;
using HSUI.Interface.GeneralElements;
using HSUI.Interface.PartyCooldowns;
using HSUI.Interface.StatusEffects;
using Dalamud.Bindings.ImGui;
using System;
using System.Numerics;

namespace HSUI.Interface.Party
{
    [Exportable(false)]
    [Section("Party Frames", true)]
    [SubSection("General", 0)]
    public class PartyFramesConfig : MovablePluginConfigObject
    {
        public new static PartyFramesConfig DefaultConfig()
        {
            var config = new PartyFramesConfig();
            config.Position = new Vector2(-ImGui.GetMainViewport().Size.X / 3 - 180, -120);

            return config;
        }

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

        [DragInt("Rows", spacing = true, isMonitored = true, min = 1, max = 8, velocity = 0.2f)]
        [Order(10)]
        public int Rows = 4;

        [DragInt("Columns", isMonitored = true, min = 1, max = 8, velocity = 0.2f)]
        [Order(11)]
        public int Columns = 2;

        [Anchor("Bars Anchor", isMonitored = true, spacing = true)]
        [Order(15)]
        public DrawAnchor BarsAnchor = DrawAnchor.TopLeft;

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

        [Checkbox("Show When Solo", spacing = true)]
        [Order(50)]
        public bool ShowWhenSolo = false;

        [Checkbox("Show Chocobo", isMonitored = true)]
        [Order(55)]
        public bool ShowChocobo = true;

        [NestedConfig("Party Title Label", 60)]
        public PartyFramesTitleLabel ShowPartyTitleConfig = new PartyFramesTitleLabel(Vector2.Zero, "", DrawAnchor.Left, DrawAnchor.Left);

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

    [Exportable(false)]
    [DisableParentSettings("FrameAnchor", "UseJobColor", "UseRoleColor")]
    public class PartyFramesTitleLabel : LabelConfig
    {
        public PartyFramesTitleLabel(Vector2 position, string text, DrawAnchor frameAnchor, DrawAnchor textAnchor) : base(position, text, frameAnchor, textAnchor)
        {
        }
    }

    [Exportable(false)]
    [Disableable(false)]
    [DisableParentSettings("Position", "Anchor", "BackgroundColor", "FillColor", "HideWhenInactive", "DrawBorder", "BorderColor", "BorderThickness")]
    [Section("Party Frames", true)]
    [SubSection("Health Bar", 0)]
    public class PartyFramesHealthBarsConfig : BarConfig
    {
        public new static PartyFramesHealthBarsConfig DefaultConfig()
        {
            var config = new PartyFramesHealthBarsConfig(Vector2.Zero, new(180, 80), PluginConfigColor.Empty);
            config.MouseoverAreaConfig.Enabled = false;

            return config;
        }

        [DragInt2("Padding", isMonitored = true, min = 0)]
        [Order(31)]
        public Vector2 Padding = new Vector2(0, 0);

        [Checkbox("Show Labels", help = "Show name, health, order number, and status text on the bar.")]
        [Order(32)]
        public bool ShowLabels = true;

        [NestedConfig("Name Label", 44)]
        public EditableLabelConfig NameLabelConfig = new EditableLabelConfig(Vector2.Zero, "[name:initials].", DrawAnchor.Center, DrawAnchor.Center);

        [NestedConfig("Health Label", 45)]
        public EditableLabelConfig HealthLabelConfig = new EditableLabelConfig(Vector2.Zero, "[health:current-short]", DrawAnchor.Right, DrawAnchor.Right);

        [NestedConfig("Order Label", 50)]
        public DefaultFontLabelConfig OrderNumberConfig = new DefaultFontLabelConfig(new Vector2(2, 4), "", DrawAnchor.TopLeft, DrawAnchor.TopLeft);

        [NestedConfig("Colors", 55)]
        public PartyFramesColorsConfig ColorsConfig = new PartyFramesColorsConfig();

        [NestedConfig("Shield", 60)]
        public ShieldConfig ShieldConfig = new ShieldConfig();

        [NestedConfig("Change Alpha Based on Range", 65)]
        public PartyFramesRangeConfig RangeConfig = new PartyFramesRangeConfig();

        [NestedConfig("Use Smooth Transitions", 70)]
        public SmoothHealthConfig SmoothHealthConfig = new SmoothHealthConfig();

        [NestedConfig("Custom Mouseover Area", 75)]
        public MouseoverAreaConfig MouseoverAreaConfig = new MouseoverAreaConfig();

        public PartyFramesHealthBarsConfig(Vector2 position, Vector2 size, PluginConfigColor fillColor, BarDirection fillDirection = BarDirection.Right)
            : base(position, size, fillColor, fillDirection)
        {
        }
    }

    [Disableable(false)]
    [Exportable(false)]
    public class PartyFramesColorsConfig : PluginConfigObject
    {
        [Checkbox("Show Border")]
        [Order(4)]
        public bool ShowBorder = true;

        [ColorEdit4("Border Color")]
        [Order(5, collapseWith = nameof(ShowBorder))]
        public PluginConfigColor BorderColor = new PluginConfigColor(new Vector4(0f / 255f, 0f / 255f, 0f / 255f, 100f / 100f));

        [ColorEdit4("Target Border Color")]
        [Order(6, collapseWith = nameof(ShowBorder))]
        public PluginConfigColor TargetBordercolor = new PluginConfigColor(new Vector4(255f / 255f, 255f / 255f, 255f / 255f, 100f / 100f));

        [DragInt("Inactive Border Thickness", min = 1, max = 10, help = "This is the border thickness that will be used when the border is in the default state (aka not targetted, not showing enmity, etc).")]
        [Order(6, collapseWith = nameof(ShowBorder))]
        public int InactiveBorderThickness = 1;

        [DragInt("Active Border Thickness", min = 1, max = 10, help = "This is the border thickness that will be used when the border active (aka targetted, showing enmity, etc).")]
        [Order(7, collapseWith = nameof(ShowBorder))]
        public int ActiveBorderThickness = 1;

        [ColorEdit4("Background Color", spacing = true)]
        [Order(15)]
        public PluginConfigColor BackgroundColor = new PluginConfigColor(new Vector4(0f / 255f, 0f / 255f, 0f / 255f, 70f / 100f));

        [ColorEdit4("Out of Reach Background Color", help = "This background color will be used when the player's data couldn't be retreived (i.e. player is disconnected)")]
        [Order(15)]
        public PluginConfigColor OutOfReachBackgroundColor = new PluginConfigColor(new Vector4(50f / 255f, 50f / 255f, 50f / 255f, 70f / 100f));

        [Checkbox("Use Death Indicator Background Color", isMonitored = true, spacing = true)]
        [Order(18)]
        public bool UseDeathIndicatorBackgroundColor = false;

        [ColorEdit4("Death Indicator Background Color")]
        [Order(19, collapseWith = nameof(UseDeathIndicatorBackgroundColor))]
        public PluginConfigColor DeathIndicatorBackgroundColor = new PluginConfigColor(new Vector4(204f / 255f, 3f / 255f, 3f / 255f, 80f / 100f));

        [Checkbox("Use Role Colors", isMonitored = true, spacing = true)]
        [Order(20)]
        public bool UseRoleColors = false;

        [NestedConfig("Color Based On Health Value", 30, collapsingHeader = false)]
        public ColorByHealthValueConfig ColorByHealth = new ColorByHealthValueConfig();

        [Checkbox("Highlight When Hovering With Cursor Or Soft Targeting", spacing = true)]
        [Order(40)]
        public bool ShowHighlight = true;

        [ColorEdit4("Highlight Color")]
        [Order(45, collapseWith = nameof(ShowHighlight))]
        public PluginConfigColor HighlightColor = new PluginConfigColor(new Vector4(255f / 255f, 255f / 255f, 255f / 255f, 5f / 100f));


        [Checkbox("Missing Health Color", spacing = true)]
        [Order(46)]
        public bool UseMissingHealthBar = false;

        [Checkbox("Job Color As Missing Health Color")]
        [Order(47, collapseWith = nameof(UseMissingHealthBar))]
        public bool UseJobColorAsMissingHealthColor = false;

        [Checkbox("Role Color As Missing Health Color")]
        [Order(48, collapseWith = nameof(UseMissingHealthBar))]
        public bool UseRoleColorAsMissingHealthColor = false;

        [ColorEdit4("Color" + "##MissingHealth")]
        [Order(49, collapseWith = nameof(UseMissingHealthBar))]
        public PluginConfigColor HealthMissingColor = new(new Vector4(255f / 255f, 0f / 255f, 0f / 255f, 100f / 100f));

        [Checkbox("Job Color As Background Color")]
        [Order(50)]
        public bool UseJobColorAsBackgroundColor = false;

        [Checkbox("Role Color As Background Color")]
        [Order(51)]
        public bool UseRoleColorAsBackgroundColor = false;

        [Checkbox("Show Enmity Border Colors", spacing = true)]
        [Order(54)]
        public bool ShowEnmityBorderColors = true;

        [ColorEdit4("Enmity Leader Color")]
        [Order(55, collapseWith = nameof(ShowEnmityBorderColors))]
        public PluginConfigColor EnmityLeaderBordercolor = new PluginConfigColor(new Vector4(255f / 255f, 40f / 255f, 40f / 255f, 100f / 100f));

        [Checkbox("Show Second Enmity")]
        [Order(60, collapseWith = nameof(ShowEnmityBorderColors))]
        public bool ShowSecondEnmity = true;

        [Checkbox("Hide Second Enmity in Light Parties")]
        [Order(65, collapseWith = nameof(ShowSecondEnmity))]
        public bool HideSecondEnmityInLightParties = true;

        [ColorEdit4("Enmity Second Color")]
        [Order(70, collapseWith = nameof(ShowSecondEnmity))]
        public PluginConfigColor EnmitySecondBordercolor = new PluginConfigColor(new Vector4(255f / 255f, 175f / 255f, 40f / 255f, 100f / 100f));
    }

    [Exportable(false)]
    public class PartyFramesRangeConfig : PluginConfigObject
    {
        [DragInt("Range (yalms)", min = 1, max = 500)]
        [Order(5)]
        public int Range = 30;

        [DragFloat("Alpha", min = 1, max = 100)]
        [Order(10)]
        public float Alpha = 25;

        [Checkbox("Use Additional Range Check")]
        [Order(15)]
        public bool UseAdditionalRangeCheck = false;

        [DragInt("Additional Range (yalms)", min = 1, max = 500)]
        [Order(20, collapseWith = nameof(UseAdditionalRangeCheck))]
        public int AdditionalRange = 15;

        [DragFloat("Additional Alpha", min = 1, max = 100)]
        [Order(25, collapseWith = nameof(UseAdditionalRangeCheck))]
        public float AdditionalAlpha = 60;

        public float AlphaForDistance(int distance, float alpha = 100f)
        {
            if (!Enabled)
            {
                return 100f;
            }

            if (!UseAdditionalRangeCheck)
            {
                return distance > Range ? Alpha : alpha;
            }

            if (Range > AdditionalRange)
            {
                return distance > Range ? Alpha : (distance > AdditionalRange ? AdditionalAlpha : alpha);
            }

            return distance > AdditionalRange ? AdditionalAlpha : (distance > Range ? Alpha : alpha);
        }
    }

    public class PartyFramesManaBarConfigConverter : PluginConfigObjectConverter
    {
        public PartyFramesManaBarConfigConverter()
        {
            NewTypeFieldConverter<bool, PartyFramesManaBarDisplayMode> converter;
            converter = new NewTypeFieldConverter<bool, PartyFramesManaBarDisplayMode>(
                "PartyFramesManaBarDisplayMode",
                PartyFramesManaBarDisplayMode.HealersOnly,
                (oldValue) =>
                {
                    return oldValue ? PartyFramesManaBarDisplayMode.HealersOnly : PartyFramesManaBarDisplayMode.Always;
                });

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

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

    public enum PartyFramesManaBarDisplayMode
    {
        HealersAndRaiseJobs,
        HealersOnly,
        Always,
    }

    [DisableParentSettings("HideWhenInactive", "Label")]
    [Exportable(false)]
    [Section("Party Frames", true)]
    [SubSection("Mana Bar", 0)]
    public class PartyFramesManaBarConfig : PrimaryResourceConfig
    {
        public new static PartyFramesManaBarConfig DefaultConfig()
        {
            var config = new PartyFramesManaBarConfig(Vector2.Zero, new(180, 6));
            config.HealthBarAnchor = DrawAnchor.Bottom;
            config.Anchor = DrawAnchor.Bottom;
            config.ValueLabel.Enabled = false;
            return config;
        }

        [Anchor("Health Bar Anchor")]
        [Order(14)]
        public DrawAnchor HealthBarAnchor = DrawAnchor.BottomLeft;

        [RadioSelector("Show For All Jobs With Raise", "Show Only For Healers", "Show For All Jobs")]
        [Order(42)]
        public PartyFramesManaBarDisplayMode ManaBarDisplayMode = PartyFramesManaBarDisplayMode.HealersOnly;

        public PartyFramesManaBarConfig(Vector2 position, Vector2 size)
            : base(position, size)
        {
        }
    }

    [Exportable(false)]
    [Section("Party Frames", true)]
    [SubSection("Castbar", 0)]
    public class PartyFramesCastbarConfig : CastbarConfig
    {
        public new static PartyFramesCastbarConfig DefaultConfig()
        {
            var size = new Vector2(182, 10);
            var pos = new Vector2(-1, 0);

            var castNameConfig = new LabelConfig(new Vector2(5, 0), "", DrawAnchor.Left, DrawAnchor.Left);
            var castTimeConfig = new NumericLabelConfig(new Vector2(-5, 0), "", DrawAnchor.Right, DrawAnchor.Right);
            castTimeConfig.Enabled = false;
            castTimeConfig.NumberFormat = 1;

            var config = new PartyFramesCastbarConfig(pos, size, castNameConfig, castTimeConfig);
            config.HealthBarAnchor = DrawAnchor.BottomLeft;
            config.Anchor = DrawAnchor.TopLeft;
            config.ShowIcon = false;
            config.Enabled = false;

            return config;
        }

        [Checkbox("Hide Name When Casting")]
        [Order(6)]
        public bool HideNameWhenCasting = false;

        [Anchor("Health Bar Anchor")]
        [Order(16)]
        public DrawAnchor HealthBarAnchor = DrawAnchor.BottomLeft;

        public PartyFramesCastbarConfig(Vector2 position, Vector2 size, LabelConfig castNameConfig, NumericLabelConfig castTimeConfig)
            : base(position, size, castNameConfig, castTimeConfig)
        {

        }
    }

    [Disableable(false)]
    [Exportable(false)]
    [Section("Party Frames", true)]
    [SubSection("Icons", 0)]
    public class PartyFramesIconsConfig : PluginConfigObject
    {
        public new static PartyFramesIconsConfig DefaultConfig() { return new PartyFramesIconsConfig(); }

        [NestedConfig("Role / Job", 10, separator = false)]
        public PartyFramesRoleIconConfig Role = new PartyFramesRoleIconConfig(
            new Vector2(20, 0),
            new Vector2(20, 20),
            DrawAnchor.TopLeft,
            DrawAnchor.TopLeft
        );

        [NestedConfig("Sign", 11)]
        public SignIconConfig Sign = new SignIconConfig(
            new Vector2(0, -10),
            new Vector2(30, 30),
            DrawAnchor.Top,
            DrawAnchor.Top
        );

        [NestedConfig("Leader", 12)]
        public PartyFramesLeaderIconConfig Leader = new PartyFramesLeaderIconConfig(
            new Vector2(-12, -12),
            new Vector2(24, 24),
            DrawAnchor.TopLeft,
            DrawAnchor.TopLeft
        );

        [NestedConfig("Player Status", 13)]
        public PartyFramesPlayerStatusConfig PlayerStatus = new PartyFramesPlayerStatusConfig();

        [NestedConfig("Ready Check Status", 14)]
        public PartyFramesReadyCheckStatusConfig ReadyCheckStatus = new PartyFramesReadyCheckStatusConfig();

        [NestedConfig("Who's Talking", 15)]
        public PartyFramesWhosTalkingConfig WhosTalking = new PartyFramesWhosTalkingConfig();
    }

    [Exportable(false)]
    public class PartyFramesRoleIconConfig : RoleJobIconConfig
    {
        public PartyFramesRoleIconConfig() : base() { }

        public PartyFramesRoleIconConfig(Vector2 position, Vector2 size, DrawAnchor anchor, DrawAnchor frameAnchor)
            : base(position, size, anchor, frameAnchor)
        {
        }
    }

    [Exportable(false)]
    public class PartyFramesLeaderIconConfig : IconConfig
    {
        public PartyFramesLeaderIconConfig() : base() { }

        public PartyFramesLeaderIconConfig(Vector2 position, Vector2 size, DrawAnchor anchor, DrawAnchor frameAnchor)
            : base(position, size, anchor, frameAnchor)
        {
        }
    }

    [Exportable(false)]
    public class PartyFramesPlayerStatusConfig : PluginConfigObject
    {
        public new static PartyFramesPlayerStatusConfig DefaultConfig()
        {
            var config = new PartyFramesPlayerStatusConfig();
            config.Label.Enabled = false;

            return config;
        }

        [Checkbox("Hide Name When Showing Status")]
        [Order(5)]
        public bool HideName = false;

        [NestedConfig("Icon", 10)]
        public IconConfig Icon = new IconConfig(
            new Vector2(0, 5),
            new Vector2(16, 16),
            DrawAnchor.Top,
            DrawAnchor.Top
        );

        [NestedConfig("Label", 15)]
        public LabelConfig Label = new LabelConfig(Vector2.Zero, "", DrawAnchor.Center, DrawAnchor.Center);
    }

    [Exportable(false)]
    public class PartyFramesReadyCheckStatusConfig : PluginConfigObject
    {
        public new static PartyFramesReadyCheckStatusConfig DefaultConfig() => new PartyFramesReadyCheckStatusConfig();

        [Checkbox("Hide Name When Showing Status")]
        [Order(5)]
        public bool HideName = false;

        [DragInt("Duration (seconds)", min = 1, max = 60, help = "Determines for how long the icons will show after a ready check is finished.")]
        [Order(6)]
        public int Duration = 10;

        [NestedConfig("Icon", 10)]
        public IconConfig Icon = new IconConfig(
            new Vector2(0, 0),
            new Vector2(24, 24),
            DrawAnchor.TopRight,
            DrawAnchor.TopRight
        );
    }

    [Exportable(false)]
    public class PartyFramesWhosTalkingConfig : PluginConfigObject
    {
        public new static PartyFramesWhosTalkingConfig DefaultConfig() => new PartyFramesWhosTalkingConfig();

        [Checkbox("Replace Role/Job Icon when active")]
        [Order(5)]
        public bool ReplaceRoleJobIcon = false;

        [Checkbox("Show Speaking State", spacing = true)]
        [Order(10)]
        public bool ShowSpeaking = true;

        [Checkbox("Show Muted State")]
        [Order(10)]
        public bool ShowMuted = true;

        [Checkbox("Show Deafened State")]
        [Order(10)]
        public bool ShowDeafened = true;

        [NestedConfig("Icon", 20)]
        public IconConfig Icon = new IconConfig(
            new Vector2(0, 0),
            new Vector2(24, 24),
            DrawAnchor.TopRight,
            DrawAnchor.TopRight
        );

        [Checkbox("Change Health Bar Border when active", spacing = true, help = "Enabling this will override other border settings!")]
        [Order(30)]
        public bool ChangeBorders = false;

        [DragInt("Border Thickness", min = 1, max = 10)]
        [Order(31, collapseWith = nameof(ChangeBorders))]
        public int BorderThickness = 1;

        [ColorEdit4("Speaking Border Color")]
        [Order(32, collapseWith = nameof(ChangeBorders))]
        public PluginConfigColor SpeakingBorderColor = PluginConfigColor.FromHex(0xFF40BB40);

        [ColorEdit4("Muted Border Color")]
        [Order(33, collapseWith = nameof(ChangeBorders))]
        public PluginConfigColor MutedBorderColor = PluginConfigColor.FromHex(0xFF008080);

        [ColorEdit4("Deafened Border Color")]
        [Order(34, collapseWith = nameof(ChangeBorders))]
        public PluginConfigColor DeafenedBorderColor = PluginConfigColor.FromHex(0xFFFF4444);

        public bool EnabledForState(WhosTalkingState state)
        {
            switch (state)
            {
                case WhosTalkingState.Speaking: return ShowSpeaking;
                case WhosTalkingState.Muted: return ShowMuted;
                case WhosTalkingState.Deafened: return ShowDeafened;
            }

            return false;
        }

        public PluginConfigColor? ColorForState(WhosTalkingState state)
        {
            if (state == WhosTalkingState.Speaking && ShowSpeaking) { return SpeakingBorderColor; }
            if (state == WhosTalkingState.Muted && ShowMuted) { return MutedBorderColor; }
            if (ShowDeafened) { return DeafenedBorderColor; }

            return null;
        }
    }

    [Exportable(false)]
    [Section("Party Frames", true)]
    [SubSection("Buffs", 0)]
    public class PartyFramesBuffsConfig : PartyFramesStatusEffectsListConfig
    {
        public new static PartyFramesBuffsConfig DefaultConfig()
        {
            var durationConfig = new LabelConfig(new Vector2(0, -4), "", DrawAnchor.Bottom, DrawAnchor.Center);
            var stacksConfig = new LabelConfig(new Vector2(-3, 4), "", DrawAnchor.TopRight, DrawAnchor.Center);
            stacksConfig.Color = new(Vector4.UnitW);
            stacksConfig.OutlineColor = new(Vector4.One);

            var iconConfig = new StatusEffectIconConfig(durationConfig, stacksConfig);
            iconConfig.DispellableBorderConfig.Enabled = false;
            iconConfig.Size = new Vector2(24, 24);

            var pos = new Vector2(-2, 2);
            var size = new Vector2(iconConfig.Size.X * 4 + 6, iconConfig.Size.Y);

            var config = new PartyFramesBuffsConfig(DrawAnchor.TopRight, pos, size, true, false, false, GrowthDirections.Left | GrowthDirections.Down, iconConfig);
            config.Limit = 4;

            return config;
        }

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

    [Exportable(false)]
    [Section("Party Frames", true)]
    [SubSection("Debuffs", 0)]
    public class PartyFramesDebuffsConfig : PartyFramesStatusEffectsListConfig
    {
        public new static PartyFramesDebuffsConfig DefaultConfig()
        {
            var durationConfig = new LabelConfig(new Vector2(0, -4), "", DrawAnchor.Bottom, DrawAnchor.Center);
            var stacksConfig = new LabelConfig(new Vector2(-3, 4), "", DrawAnchor.TopRight, DrawAnchor.Center);
            stacksConfig.Color = new(Vector4.UnitW);
            stacksConfig.OutlineColor = new(Vector4.One);

            var iconConfig = new StatusEffectIconConfig(durationConfig, stacksConfig);
            iconConfig.Size = new Vector2(24, 24);

            var pos = new Vector2(-2, -2);
            var size = new Vector2(iconConfig.Size.X * 4 + 6, iconConfig.Size.Y);

            var config = new PartyFramesDebuffsConfig(DrawAnchor.BottomRight, pos, size, false, true, false, GrowthDirections.Left | GrowthDirections.Up, iconConfig);
            config.Limit = 4;

            return config;
        }

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

    public class PartyFramesStatusEffectsListConfig : StatusEffectsListConfig
    {
        [Anchor("Health Bar Anchor")]
        [Order(4)]
        public DrawAnchor HealthBarAnchor = DrawAnchor.BottomLeft;

        public PartyFramesStatusEffectsListConfig(DrawAnchor anchor, Vector2 position, Vector2 size, bool showBuffs, bool showDebuffs, bool showPermanentEffects,
            GrowthDirections growthDirections, StatusEffectIconConfig iconConfig)
            : base(position, size, showBuffs, showDebuffs, showPermanentEffects, growthDirections, iconConfig)
        {
            HealthBarAnchor = anchor;
        }
    }

    [Disableable(false)]
    [Exportable(false)]
    [Section("Party Frames", true)]
    [SubSection("Trackers", 0)]
    public class PartyFramesTrackersConfig : PluginConfigObject
    {
        public new static PartyFramesTrackersConfig DefaultConfig() { return new PartyFramesTrackersConfig(); }

        [NestedConfig("Raise Tracker", 10, separator = false)]
        public PartyFramesRaiseTrackerConfig Raise = new PartyFramesRaiseTrackerConfig();

        [NestedConfig("Invulnerabilities Tracker", 15)]
        public PartyFramesInvulnTrackerConfig Invuln = new PartyFramesInvulnTrackerConfig();

        [NestedConfig("Cleanse Tracker", 15)]
        public PartyFramesCleanseTrackerConfig Cleanse = new PartyFramesCleanseTrackerConfig();
    }

    [Exportable(false)]
    public class PartyFramesRaiseTrackerConfig : PluginConfigObject
    {
        public new static PartyFramesRaiseTrackerConfig DefaultConfig() { return new PartyFramesRaiseTrackerConfig(); }

        [Checkbox("Hide Name When Raised")]
        [Order(10)]
        public bool HideNameWhenRaised = true;

        [Checkbox("Keep Icon After Cast Finishes")]
        [Order(15)]
        public bool KeepIconAfterCastFinishes = true;

        [Checkbox("Change Background Color When Raised", spacing = true)]
        [Order(20)]
        public bool ChangeBackgroundColorWhenRaised = true;

        [ColorEdit4("Raise Background Color")]
        [Order(25, collapseWith = nameof(ChangeBackgroundColorWhenRaised))]
        public PluginConfigColor BackgroundColor = new(new Vector4(211f / 255f, 235f / 255f, 215f / 245f, 50f / 100f));

        [Checkbox("Change Border Color When Raised", spacing = true)]
        [Order(30)]
        public bool ChangeBorderColorWhenRaised = true;

        [ColorEdit4("Raise Border Color")]
        [Order(35, collapseWith = nameof(ChangeBorderColorWhenRaised))]
        public PluginConfigColor BorderColor = new(new Vector4(47f / 255f, 169f / 255f, 215f / 255f, 100f / 100f));

        [NestedConfig("Icon", 50)]
        public IconWithLabelConfig Icon = new IconWithLabelConfig(
            new Vector2(0, 0),
            new Vector2(50, 50),
            DrawAnchor.Center,
            DrawAnchor.Center
        );
    }

    [Exportable(false)]
    public class PartyFramesInvulnTrackerConfig : PluginConfigObject
    {
        public new static PartyFramesInvulnTrackerConfig DefaultConfig() { return new PartyFramesInvulnTrackerConfig(); }

        [Checkbox("Hide Name When Invuln is Up")]
        [Order(10)]
        public bool HideNameWhenInvuln = true;

        [Checkbox("Change Background Color When Invuln is Up", spacing = true)]
        [Order(15)]
        public bool ChangeBackgroundColorWhenInvuln = true;

        [ColorEdit4("Invuln Background Color")]
        [Order(20, collapseWith = nameof(ChangeBackgroundColorWhenInvuln))]
        public PluginConfigColor BackgroundColor = new(new Vector4(211f / 255f, 235f / 255f, 215f / 245f, 50f / 100f));

        [Checkbox("Walking Dead Custom Color")]
        [Order(25, collapseWith = nameof(ChangeBackgroundColorWhenInvuln))]
        public bool UseCustomWalkingDeadColor = true;

        [ColorEdit4("Walking Dead Background Color")]
        [Order(30, collapseWith = nameof(UseCustomWalkingDeadColor))]
        public PluginConfigColor WalkingDeadBackgroundColor = new(new Vector4(158f / 255f, 158f / 255f, 158f / 255f, 50f / 100f));

        [NestedConfig("Icon", 50)]
        public IconWithLabelConfig Icon = new IconWithLabelConfig(
            new Vector2(0, 0),
            new Vector2(50, 50),
            DrawAnchor.Center,
            DrawAnchor.Center
        );
    }

    public class PartyFramesTrackerConfigConverter : PluginConfigObjectConverter
    {
        public PartyFramesTrackerConfigConverter()
        {
            SameTypeFieldConverter<Vector2> pos = new SameTypeFieldConverter<Vector2>("Icon.Position", Vector2.Zero);
            FieldConvertersMap.Add("Position", pos);

            SameTypeFieldConverter<Vector2> size = new SameTypeFieldConverter<Vector2>("Icon.Size", new Vector2(50, 50));
            FieldConvertersMap.Add("IconSize", size);

            SameTypeFieldConverter<DrawAnchor> anchor = new SameTypeFieldConverter<DrawAnchor>("Icon.Anchor", DrawAnchor.Center);
            FieldConvertersMap.Add("Anchor", anchor);

            SameTypeFieldConverter<DrawAnchor> frameAnchor = new SameTypeFieldConverter<DrawAnchor>("Icon.FrameAnchor", DrawAnchor.Center);
            FieldConvertersMap.Add("HealthBarAnchor", frameAnchor);
        }

        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(PartyFramesRaiseTrackerConfig) ||
                   objectType == typeof(PartyFramesInvulnTrackerConfig);
        }
    }

    [DisableParentSettings("Position", "Strata")]
    [Exportable(false)]
    public class PartyFramesCleanseTrackerConfig : MovablePluginConfigObject
    {
        public new static PartyFramesCleanseTrackerConfig DefaultConfig() { return new PartyFramesCleanseTrackerConfig(); }

        [Checkbox("Show only on jobs with cleanses", spacing = true)]
        [Order(10)]
        public bool CleanseJobsOnly = true;

        [Checkbox("Change Health Bar Color ", spacing = true)]
        [Order(15)]
        public bool ChangeHealthBarCleanseColor = true;

        [ColorEdit4("Health Bar Color")]
        [Order(20, collapseWith = nameof(ChangeHealthBarCleanseColor))]
        public PluginConfigColor HealthBarColor = new(new Vector4(255f / 255f, 0f / 255f, 104f / 255f, 100f / 100f));

        [Checkbox("Change Border Color", spacing = true)]
        [Order(25)]
        public bool ChangeBorderCleanseColor = true;

        [ColorEdit4("Border Color")]
        [Order(30, collapseWith = nameof(ChangeBorderCleanseColor))]
        public PluginConfigColor BorderColor = new(new Vector4(255f / 255f, 0f / 255f, 104f / 255f, 100f / 100f));
    }

    [Exportable(false)]
    [DisableParentSettings("Anchor")]
    [Section("Party Frames", true)]
    [SubSection("Cooldowns", 0)]
    public class PartyFramesCooldownListConfig : AnchorablePluginConfigObject
    {
        public new static PartyFramesCooldownListConfig DefaultConfig()
        {
            PartyFramesCooldownListConfig config = new PartyFramesCooldownListConfig();
            config.Position = new Vector2(-2, 0);
            config.Size = new Vector2(40 * 8 + 6, 40);

            return config;
        }

        [Anchor("Health Bar Anchor")]
        [Order(3)]
        public DrawAnchor HealthBarAnchor = DrawAnchor.Left;

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

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

        [DragInt2("Icon Size", min = 1, max = 4000, spacing = true)]
        [Order(30)]
        public Vector2 IconSize = new Vector2(40, 40);

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

        [Checkbox("Fill Rows First")]
        [Order(32)]
        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(33)]
        public int Directions = 3; // left & up

        [Checkbox("Show Border", spacing = true)]
        [Order(35)]
        public bool DrawBorder = true;

        [ColorEdit4("Border Color")]
        [Order(36, collapseWith = nameof(DrawBorder))]
        public PluginConfigColor BorderColor = new PluginConfigColor(new Vector4(0f / 255f, 0f / 255f, 0f / 255f, 100f / 100f));

        [DragInt("Border Thickness", min = 1, max = 10)]
        [Order(37, collapseWith = nameof(DrawBorder))]
        public int BorderThickness = 1;

        [Checkbox("Change Icon Border When Active")]
        [Order(45, collapseWith = nameof(DrawBorder))]
        public bool ChangeIconBorderWhenActive = true;

        [ColorEdit4("Icon Active Border Color")]
        [Order(46, collapseWith = nameof(ChangeIconBorderWhenActive))]
        public PluginConfigColor IconActiveBorderColor = new PluginConfigColor(new Vector4(255f / 255f, 200f / 255f, 35f / 255f, 100f / 100f));

        [DragInt("Icon Active Border Thickness", min = 1, max = 10)]
        [Order(47, collapseWith = nameof(ChangeIconBorderWhenActive))]
        public int IconActiveBorderThickness = 3;

        [Checkbox("Change Label Color When Active", spacing = true)]
        [Order(50)]
        public bool ChangeLabelsColorWhenActive = false;

        [ColorEdit4("Label Active Color")]
        [Order(51, collapseWith = nameof(ChangeLabelsColorWhenActive))]
        public PluginConfigColor LabelsActiveColor = new PluginConfigColor(new Vector4(255f / 255f, 200f / 255f, 35f / 255f, 100f / 100f));

        [NestedConfig("Time Label", 80)]
        public PartyCooldownTimeLabelConfig TimeLabel = new PartyCooldownTimeLabelConfig(new Vector2(0, 0), "", DrawAnchor.Center, DrawAnchor.Center) { NumberFormat = 1 };
    }
}
