using System.ComponentModel;
using System.Reflection;
using GraphicsManager.Enums;
using GraphicsManager.Interfaces;
using GraphicsManager.Objects;
using Luski.net.Structures.Public;
using Luski.Shared.PublicServers.V1.Enums;
using OpenTK.Mathematics;
using DisplayNameAttribute = Luski.Shared.GlobalAttributes.DisplayNameAttribute;

namespace Luski.GUI.MainScreen.UI.PublicServers.ServerSettings.Pages.Server.Roles;

public class ServerRoleOptions : UserControl
{
    public FlowLayout Page = new();
    private Label Display = new(Globals.DefaultFont) { Text = "Display" }, Permissions = new(Globals.DefaultFont) { Text = "Permissions" }, ManageMembers = new(Globals.DefaultFont);
    private Rectangle Line = new() {BackgroundColor = new(63,65,71,255)}, SelectedLine = new();

    private SaveWarning Warning;
    
    public delegate void LoadCurrent();

    private LoadCurrent? CurrentPageToLoad = null;
    
    public void Init(SaveWarning sw)
    {
        Warning = sw;
        Controls.Add(Display);
        Controls.Add(Permissions);
        Controls.Add(ManageMembers);
        Controls.Add(Line);
        Controls.Add(SelectedLine);
        Controls.Add(Page);
        Page.BackgroundColor = new(0, 0, 0, 0);
        base.BackgroundColor = new(0, 0, 0, 0);
        int space = 20.ScaleInt();
        Display.Location = new(space, 0);
        Permissions.Location = new(Display.Location.X + Display.Size.X + space, Permissions.Location.Y);
        ManageMembers.Location = new(Permissions.Location.X + Permissions.Size.X + space, ManageMembers.Location.Y);
        Line.Location = new(space, Display.Size.Y);
        Line.Size = new(Size.X - space - space, 2.ScaleInt());
        Line.Anchor = ObjectAnchor.Left | ObjectAnchor.Right | ObjectAnchor.Top;
        Line.ForceDistanceUpdate(this);
        SelectedLine.Location = new(Display.Location.X, Line.Location.Y);
        SelectedLine.BackgroundColor = Globals.DodgerBlue;
        SelectedLine.Size = new(Display.Size.X, Line.Size.Y);
        Display.Clicked += _ =>
        {
            if (SelectedLine.Location.X == Display.Location.X) return Task.CompletedTask;
            LoadDisplay();
            return Task.CompletedTask;
        };
        Permissions.Clicked += _ =>
        {
            if (SelectedLine.Location.X == Permissions.Location.X) return Task.CompletedTask;
            LoadPermissions();
            return Task.CompletedTask;
        };
        ManageMembers.Clicked += _ =>
        {
            if (SelectedLine.Location.X == ManageMembers.Location.X) return Task.CompletedTask;
            LoadMembers();
            return Task.CompletedTask;
        };
        Page.Size = new(Line.Size.X, base.Size.Y - Line.Location.Y - Line.Size.Y);
        Page.Location = new(Line.Location.X, Line.Size.Y + Line.Location.Y);
        Page.HScrollPixels = (uint)30.ScaleInt();
        Page.Anchor = ObjectAnchor.All;
        Page.ForceDistanceUpdate(this);
        if (LuskiExperiments.GUI.LiveLabelSize.IsEnabled())
            Page.SizeChanged += PageOnSizeChanged;
        LuskiExperiments.GUI.LiveLabelSize.EventToggled += b =>
        {
            if (b) Page.SizeChanged += PageOnSizeChanged;
            else Page.SizeChanged -= PageOnSizeChanged;
            return Task.CompletedTask;
        };
    }

    private Task PageOnSizeChanged(IRenderObject arg)
    {
        foreach (Label l in NeedMax)
        {
            Vector2i oldsize = l.Size;
            l.MaxSize = Page.Size;
            Vector2i diff = oldsize - l.Size;
            if (l.Parent is UserControl uc)
            {
                uc.Size = new(uc.Size.X, uc.Size.Y - diff.Y);
            }
            if (l.Tag is Rectangle line)
            {
                line.Location = new(line.Location.X, line.Location.Y - diff.Y);
            }
        }
        return Task.CompletedTask;
    }

    private List<Label> NeedMax = new();

    private void AddSpace()
    {
        int space = Warning.Parent!.Size.Y - Warning.Location.Y - Warning.Size.Y;
        Page.Controls.Add(new Rectangle()
        {
            BackgroundColor = new(0,0,0,0),
            Size = new(Warning.Size.Y + space + space)
        });
    }
    
    public void LoadDisplay()
    {
        if (CurrentPageToLoad != LoadDisplay)
        {
            Page.ScrollToTop();
        }
        CurrentPageToLoad = LoadDisplay;
        SelectedLine.Size = new(Display.Size.X, Line.Size.Y);
        SelectedLine.Location = new(Display.Location.X, Line.Location.Y);
        Page.Controls.Clear();
        TryDraw();
    }

    private ServerPermission TempPermissions = ServerPermission.None;

    public void LoadPermissions()
    {
        uint? scrval = null;
        if (CurrentPageToLoad != LoadPermissions)
        {
            scrval = Page.ScrollValue;
            Page.ScrollToTop();
        }
        CurrentPageToLoad = LoadPermissions;
        SelectedLine.Size = new(Permissions.Size.X, Line.Size.Y);
        SelectedLine.Location = new(Permissions.Location.X, Line.Location.Y);
        RemoveSaveEvents();
        BlockDraw = true;
        Page.Controls.Clear();
        TempPermissions = r.ServerPermissions;
        NeedMax.Clear();
        Type PropType = typeof(ServerPermission);
        IEnumerable<ServerPermission> values = Enum.GetValues(PropType).Cast<ServerPermission>();
        Dictionary<string, UserControl> Cats = new();
        foreach (var val in values)
        {
            try
            {
                MemberInfo? enumValueMemberInfo = Globals.GetMemberInfo(PropType, val);
                string description = Globals.GetAttribute<DescriptionAttribute, ServerPermission>(enumValueMemberInfo!, val).Description;
                string Name = Globals.GetAttribute<DisplayNameAttribute, ServerPermission>(enumValueMemberInfo!, val).DisplayName;
                string cat = Globals.GetAttribute<CategoryAttribute, ServerPermission>(enumValueMemberInfo!, val).Category;
                if (cat.ToLower() == "internal") continue;

                if (!Cats.ContainsKey(cat))
                {
                    UserControl c = new UserControl()
                    {
                        BackgroundColor = Page.BackgroundColor,
                        Size = new(Page.Size.X, 50.ScaleInt())
                    };
                    Label tmp = new(Globals.DefaultFont)
                    {
                        Text = cat + " Permissions"
                    };
                    tmp.SetLocation(2.ScaleInt(), (int)((c.Size.Y - tmp.Font.PixelHeight)/2));
                    c.Controls.Add(tmp);
                    Page.Controls.Add(c);
                    Cats.Add(cat, c);
                }
                
                UserControl tc = Globals.AddBool(Cats[cat], Name, description + " in the server.", r.ServerPermissions.HasFlag(val), _ =>
                {
                    TempPermissions ^= val;
                    if (TempPermissions != r.ServerPermissions)
                    {
                        Warning.Visible = true;
                    }
                    else
                    {
                        Warning.Visible = false;
                    }
                }, NeedMax);
                tc.SetLocation(tc.Location.X, Cats[cat].Size.Y);
                Cats[cat].SetSize(Cats[cat].Size.X, Cats[cat].Size.Y + tc.Size.Y);
               
            }
            catch
            {
                //ignore
            }
        }
        AddSpace();
        Warning.SaveClicked += PermissionSave;
        if (scrval is not null)
        {
            Page.ScrollValue = scrval.Value;
        }
        BlockDraw = false;
        TryDraw();
    }

    private async Task PermissionSave()
    {
        r = await r.Server.EditRole(r, Permissions: TempPermissions);
        Window!.Invoke(() =>
        {
            Warning.Visible = false;
            Window!.TryDraw();
        });
        TempPermissions = r.ServerPermissions;
    }

    public void RemoveSaveEvents()
    {
        Warning.SaveClicked -= PermissionSave;
    }
    
    public void LoadMembers()
    {
        if (CurrentPageToLoad != LoadMembers)
        {
            Page.ScrollToTop();
        }
        CurrentPageToLoad = LoadMembers;
        BlockDraw = true;
        SelectedLine.Size = new(ManageMembers.Size.X, Line.Size.Y);
        SelectedLine.Location = new(ManageMembers.Location.X, Line.Location.Y);
        Page.Controls.Clear();
        var m = r.GetMembers();
        m.Wait();
        foreach (var meber in m.Result)
        {
            var p = meber.Server.GetProfile(meber.ServerProfile, CancellationToken.None);
            p.Wait();
            Page.Controls.Add(new RoleMember(p.Result, meber)
            {
                BackgroundColor = Page.BackgroundColor
            });
        }
        BlockDraw = false;
        TryDraw();
    }

    private Role r;
    
    public void LoadRole(Role role)
    {
        r = role;
        ManageMembers.Text = $"Manage Members ({role.MembersListID.Length})";
        if (CurrentPageToLoad is not null) CurrentPageToLoad();
        //LoadPermissions();
    }
}