using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
using GraphicsManager.Enums;
using GraphicsManager.Interfaces;
using GraphicsManager.Objects;
using GraphicsManager.Objects.Core;
using Luski.GUI.MainScreen.UI;
using Luski.GUI.MainScreen.UI.Generic;
using Luski.GUI.MainScreen.UI.LuskiControls;
using Luski.GUI.MainScreen.UI.LuskiSettings;
using Luski.GUI.MainScreen.UI.PublicServers;
using Luski.GUI.MainScreen.UI.PublicServers.ServerSettings;
using Luski.net;
using Luski.net.Structures.Public;
using Luski.Shared.PublicServers.V1.Enums;
using OpenTK.Graphics.OpenGL4;
using OpenTK.Mathematics;
using OpenTK.Windowing.Common;
using OpenTK.Windowing.Desktop;
using OpenTK.Windowing.GraphicsLibraryFramework;
using DebugProc = OpenTK.Graphics.OpenGL4.DebugProc;
using DebugSeverity = OpenTK.Graphics.OpenGL4.DebugSeverity;
using DebugSource = OpenTK.Graphics.OpenGL4.DebugSource;
using DebugType = OpenTK.Graphics.OpenGL4.DebugType;
using ErrorCode = OpenTK.Windowing.GraphicsLibraryFramework.ErrorCode;
using Window = GraphicsManager.Window;

namespace Luski.GUI;

public class MainScreenWindow : Window
{
    public static readonly NativeWindowSettings Settings = new()
    {
        Title = "Luski",
        WindowBorder = WindowBorder.Resizable,
        APIVersion = new Version(3, 2),
        API = ContextAPI.OpenGL,
        StartFocused = true,
        ClientSize = new Vector2i(624, 1090),
        Icon = Globals.Icon,
        SharedContext = null,
    };

    public TabControl? tc;
    private FlowLayout? channelpicker, friends, friend_request;
    private RoundedButton? FriendManagerBtn;
    public static DebugProc DebugMessageDelegate = OnDebugMessage;
    private static GLFWCallbacks.ErrorCallback GLFW_Error = OnGLFW_Error;

    private static void OnGLFW_Error(ErrorCode e, string d)
    {
        if ((Globals.Settings.Logs & ConsoleLog.ShowErrorsForGLFW) != ConsoleLog.ShowErrorsForGLFW) return;
        Console.ForegroundColor = ConsoleColor.DarkRed;
        Console.WriteLine("[GLFW Error:{0}] {1}", e, d);
        Console.ResetColor();
    }

    private static void OnDebugMessage(
        DebugSource source, // Source of the debugging message.
        DebugType type, // Type of the debugging message.
        int id, // ID associated with the message.
        DebugSeverity severity, // Severity of the message.
        int length, // Length of the string in pMessage.
        IntPtr pMessage, // Pointer to message string.
        IntPtr pUserParam) // The pointer you gave to OpenGL, explained later.
    {
        string message = string.Empty;

        switch (severity)
        {
            case DebugSeverity.DebugSeverityHigh:
                if ((Globals.Settings.Logs & ConsoleLog.BigErrosForOpenGL) == ConsoleLog.BigErrosForOpenGL)
                {
                    message = Marshal.PtrToStringAnsi(pMessage, length);
                    Console.ForegroundColor = ConsoleColor.DarkRed;
                    Console.WriteLine("[{0} source={1} type={2} id={3}] {4}", severity, source, type, id, message);
                    Console.ResetColor();
                }

                break;
            case DebugSeverity.DebugSeverityMedium:
                if ((Globals.Settings.Logs & ConsoleLog.MediumErrosForOpenGL) == ConsoleLog.MediumErrosForOpenGL)
                {
                    message = Marshal.PtrToStringAnsi(pMessage, length);
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    Console.WriteLine("[{0} source={1} type={2} id={3}] {4}", severity, source, type, id, message);
                    Console.ResetColor();
                }
                break;
            case DebugSeverity.DebugSeverityLow:
                if ((Globals.Settings.Logs & ConsoleLog.LowErrosForOpenGL) == ConsoleLog.LowErrosForOpenGL)
                {
                    message = Marshal.PtrToStringAnsi(pMessage, length);
                    Console.ForegroundColor = ConsoleColor.DarkYellow;
                    Console.WriteLine("[{0} source={1} type={2} id={3}] {4}", severity, source, type, id, message);
                    Console.ResetColor();
                }
                break;
            default:
                if ((Globals.Settings.Logs & ConsoleLog.InfoForOpenGL) == ConsoleLog.InfoForOpenGL)
                {
                    message = Marshal.PtrToStringAnsi(pMessage, length);
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.WriteLine(message);
                    Console.ResetColor();
                }
                break;
        }
    }

    public MainScreenWindow() : base(Settings)
    {
        if (LuskiExperiments.GUI.SubFrames.IsEnabled())
        {
            UseSubFrames = true;
        }

        LuskiExperiments.GUI.SubFrames.EventToggled += b =>
        {
            UseSubFrames = b;
            return Task.CompletedTask;
        };
        
        if (LuskiExperiments.GUI.LiveViews.IsEnabled())
        {
            UseLiveView = true;
        }

        LuskiExperiments.GUI.LiveViews.EventToggled += b =>
        {
            UseLiveView = b;
            return Task.CompletedTask;
        };
        Globals.ms = this;
        SetWindowSize(new(1332.ScaleInt(), 866.ScaleInt()));
        Shader s = new Shader("Luski.Resources.Shaders.LeftToRightLabel", Embeded: true, Assembly: Assembly.GetExecutingAssembly());
        s.Use();
        s.SetInt("u_texture", s.GetUniformLocation("u_texture"));
        Globals.GradientShader.Add(Context, s);
        ClientSize = CS;
        ShowMissingChar = true;
        LogFrames = ((Globals.Settings.Logs & ConsoleLog.DrawFrames) == ConsoleLog.DrawFrames);
        VSync = VSyncMode.On;
        GL.DebugMessageCallback(DebugMessageDelegate, IntPtr.Zero);
        GL.Enable(EnableCap.DebugOutput);
        GLFW.SetErrorCallback(GLFW_Error);
        try
        {
            Globals.DefaultFontFamly = FontFamily.LoadFontFamily(Globals.GetResource("Fonts.OpenSans.zip"), "OpenSans");
            Globals.DefaultFont = FontInteraction.Load(Globals.DefaultFontFamly);
            string fams = Path.Combine(Globals.LuskiPath, "FontFamilies");
            if (!Directory.Exists(fams)) Directory.CreateDirectory(fams);
            DirectoryInfo di = new DirectoryInfo(fams);
            
            foreach (FileInfo fam in di.GetFiles())
            {
                try
                {
                    if (fam.FullName.ToLower().EndsWith(".zip"))
                        Globals.DefaultFont.AddFamily(FontFamily.LoadFontFamily(File.Open(fam.FullName, FileMode.Open), fam.Name));
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                }
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }

        Globals.DefaultFont.PixelHeight = Globals.Settings.DefaultFontPX.ScaleFont();
        Globals.DefaultFont.FontSize = FontSize.Regular;
        Globals.TopTimeFont = Globals.DefaultFont.Clone();
        Globals.TopTimeFont.PixelHeight = Globals.Settings.TopTimeFontPX.ScaleFont();
        Globals.TopTimeFont.FontSize = FontSize.Regular;
        Globals.ServerRoleFont = Globals.DefaultFont.Clone();
        Globals.ServerRoleFont.PixelHeight = Globals.Settings.RoleSettingsFontPX.ScaleFont();
        Globals.ServerRoleFont.FontSize = FontSize.Regular;
        Globals.MessageFont = Globals.DefaultFont.Clone();
        Globals.MessageFont.PixelHeight = Globals.Settings.MessageFontPX.ScaleFont();
        Globals.MessageFont.ExtraLinePixels = Globals.Settings.MessageFontLineSpacePX.ScaleFont();
        Globals.MessageFont.FontSize = FontSize.Regular;
        Globals.SmallTimeFont = Globals.DefaultFont.Clone();
        Globals.SmallTimeFont.PixelHeight = ((uint)11).ScaleFont();
        Globals.LuskiTexture = TextureManager.GetTextureResource("Luski.png");
        try
        {
            CenterWindow(Globals.Settings.Display);
        }
        catch (Exception e)
        {
            CenterWindow();
        }
        WindowLoaded += OnWindowLoaded;
        BlockDraw = true;
    }

    private async Task OnWindowLoaded(Window arg)
    {
        BlockDraw = false;
        string irl =
            $"https://www.jacobtech.com/Updater/GetProgramVersion?directory=Luski&branch=main&selfcontained={Globals.UpdaterSettings.SelfContained.ToString().ToLower()}&platform={Globals.UpdaterSettings.Platform}";
        if (Globals.UpdaterSettings.AutoUpdateCheck && new HttpClient()
                .GetAsync(
                    irl)
                .Result.Content.ReadAsStringAsync().Result !=
            FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion)
        {
            var update = new UpdateWindow();
            var result = update.ShowDialogue(this);
            if (result == UpdateWindow.DialogueResult.Yes)
            {
                Globals.Download = true;
                Close();
            }
        }
        await LoginOnChangeToApp();
    }
    
    public ServerFlow ServerFlow;
    private UserControl ServerTitle;
    public PublicChat ChatBoxArea;
    public ChannelSelector ChannelSelector;
    


    public async Task LoadPublicServer(PublicServer? Server)
    {
        GL.Enable(EnableCap.DepthTest);
        GL.Enable(EnableCap.Multisample);
        GL.DepthFunc(DepthFunction.Always);
        if (Server is null) return;
        if (!Server.IsLogedIn)
        {
            ServerLoginOverlay SLO = new(Server.Domain);
            Controls.Add(SLO);
            ForceUpdate();
            return;
        }
        BlockDraw = true;
        try
        {
            #region Control Removing

            ServerTitle.Controls.Clear();
            ChannelSelector.Controls.Clear();
            Controls.Remove(ServerTitle, false);
            Controls.Remove(ChannelSelector, false);
            Controls.Remove(ServerFlow, false);
            Controls.Clear();
            Controls.Add(ServerTitle);
            Controls.Add(ChannelSelector);
            Controls.Add(ServerFlow);

            #endregion
            
            #region Server Title
            
            Label title = new(Globals.DefaultFont)
            {
                Text = Server.Name,
                IgnoreHover = true
            };
            if (await Server.User.HasPermissions(ServerPermission.ManageRoles))
            {
                ServerTitle.Clicked += _ =>
                {
                    PublicServerSettingsMenu sm = new(Server);
                    Controls.Add(sm);
                    Globals.ms.DrawFrame();
                    Globals.ms.ForceUpdate();
                    Globals.ms.DrawFrame();
                    return Task.CompletedTask;
                };
                title.Color = Color4.Green;
            }
            title.Location = new(5.ScaleInt(), (int)((ServerTitle.Size.Y - title.LineHeight) / 2));
            ServerTitle.Controls.Add(title);
            ServerTitle.ForceDistanceUpdate(this);

            #endregion
            
            #region Channel Selector Init

            SocketChannel current_channel = await Server.User.GetSelectedChannel(CancellationToken.None);
            List<SocketCategory> parents = new();
            SocketCategory? cur = await current_channel.GetParent();
            while (cur is not null)
            {
                parents.Add(cur);
                cur = await cur.GetParent();
            }

            parents.Reverse();
            await ChannelSelector.LoadSelectorRoot(parents[0]);
            
            parents.RemoveAt(0);
            
            #endregion

            #region Chat Init

            ChatBoxArea = new()
            {
                Anchor = ObjectAnchor.All,
                Location = new(ChannelSelector.Size.X + ServerFlow.Size.X, 0),
                Size = new(Size.X - ChannelSelector.Size.X - ServerFlow.Size.X, CS.Y),
            };
            Controls.Add(ChatBoxArea);
            ChatBoxArea.LoadToParent(this, this);
            ChatBoxArea.ForceDistanceUpdate();
            ChatBoxArea.MessageFlow.ForceDistanceUpdate(ChatBoxArea);
            #endregion

            #region Channel Selector Loader

            _ = ChannelSelector.Load(current_channel, parents);

            #endregion

            #region User Icon
            ServerProfile DefaultProfile = await Server.GetProfile(Server.User.ServerProfile, CancellationToken.None);
            IRenderObject u = await DefaultProfile.MakeRct(Server.User, new(46.ScaleInt()));
            int ii = 4.ScaleInt();
            u.Location = new(ii + ServerFlow.Size.X, ChannelSelector.Location.Y + ChannelSelector.Size.Y + ii);
            u.Anchor = ObjectAnchor.Bottom | ObjectAnchor.Left;
            Controls.Add(u);
            u.LoadToParent(this, this);
            u.ForceDistanceUpdate();
            string name = DefaultProfile.DisplayName;
            Role r = (await Server.User.GetRoles())[0];
            if (r.ColorType == ColorType.Full)
            {
                name = $"[color=\"{r.Colors[0].ToDatabaseStr()}\"]{name}[/color]";
            }
            else
            {
                name = $"[gradient colors=\"{r.Colors.ToDB()}\"]{name}[/gradient]";
            }
            LuskiLabel ul = new(Globals.DefaultFont)
            {
                Anchor = u.Anchor,
                Text = name,
            };

            ul.Location = new(u.Location.X + u.Size.X + 5.ScaleInt(),
                (u.Location.Y + ((u.Size.Y - ul.Size.Y) / 2)));
            Rectangle Expand = new(TextureManager.GetTextureResource("Expand.png"))
            {
                Size = new(20.ScaleInt()),
                Shader = Rectangle.DefaultAlphaShader[Context],
                BackgroundColor = Color4.Gray,
                Tag = new Tuple<SocketAppUser, IRenderObject, LabelBase>(Server.User, u, ul),
                Anchor = u.Anchor
            };
            Expand.Clicked += ExpandOnClicked;
            Expand.MouseEnter += _ =>
            {
                Expand.BackgroundColor = Color4.White;
                return Task.CompletedTask;
            };
            Expand.MouseLeave += _ =>
            {
                Expand.BackgroundColor = Color4.Gray;
                return Task.CompletedTask;
            };
            Expand.Location = new(ul.Location.X + ul.Size.X + 5.ScaleInt(),
                u.Location.Y + ((u.Size.Y - Expand.Size.Y) / 2));
            Expand.ForceDistanceUpdate(this);
            Controls.Add(Expand);
            Controls.Add(ul);
            Rectangle setting = new(TextureManager.GetTextureResource("settings.png"))
            {
                Location = new(ChannelSelector.Size.X - 40.ScaleInt() + ServerFlow.Size.X, ChannelSelector.Location.Y + ChannelSelector.Size.Y + 11.ScaleInt()),
                Size = new(32.ScaleInt()),
                Shader = Rectangle.DefaultAlphaShader[Context],
                BackgroundColor = Color4.Gray,
                Anchor = ObjectAnchor.Bottom | ObjectAnchor.Left,
                BlendOverride = true
            };
            setting.MouseEnter += _ =>
            {
                setting.BackgroundColor = Color4.White;
                return Task.CompletedTask;
            };
            setting.MouseLeave += _ =>
            {
                setting.BackgroundColor = Color4.Gray;
                return Task.CompletedTask;
            };
            setting.Clicked += SettingOnClicked;
            setting.ForceDistanceUpdate(this);
            Controls.Add(setting);
            ForceUpdate();
            TryDraw();
            #endregion
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }

        BlockDraw = false;
    }

    private FlowLayout? ProfileFlow;

    public override void ForceUpdate(bool resize = false)
    {
        base.ForceUpdate(resize && LuskiExperiments.GUI.BufferCopy.IsEnabled());
    }

    private async Task ExpandOnClicked(IRenderObject arg)
    {
        try
        {
            if (ProfileFlow is null)
            {
                ProfileFlow = new();
                Tuple<SocketAppUser, IRenderObject, LabelBase> s = (Tuple<SocketAppUser, IRenderObject, LabelBase>)arg.Tag!;
                var role = (await s.Item1.GetRoles())[0];
                foreach (ServerProfile prof in await s.Item1.GetProfiles(CancellationToken.None))
                {
                    ProfileView con = await ProfileView.Make(s.Item1, prof, role);
                    con.Clicked += async _ =>
                    {
                        IRenderObject iro = await prof.MakeRct(s.Item1, s.Item2.Size);
                        iro.Location = s.Item2.Location;
                        iro.Distance = s.Item2.Distance;
                        iro.Anchor = s.Item2.Anchor;
                        int oldx = s.Item3.Size.X;
                        s.Item2.Parent!.Controls.Add(iro);
                        s.Item2.Parent!.Controls.Remove(s.Item2);
                        s.Item3.Text = prof.DisplayName;
                        Controls.Remove(ProfileFlow);
                        ProfileFlow = null;
                        arg.Location = new(arg.Location.X - oldx + s.Item3.Size.X, arg.Location.Y);
                        arg.ForceDistanceUpdate(arg.Parent!);
                        Globals.ServerProfile = prof;
                        arg.Tag = new Tuple<SocketAppUser, IRenderObject, LabelBase>(s.Item1, iro, s.Item3);
                        TryDraw();
                    };
                    ProfileFlow.Controls.Add(con);
                    ProfileFlow.Size = new((int)arg.SizeAsFloat.X, ProfileFlow.Size.Y + con.Size.Y);
                }

                ProfileFlow.Location = new(ServerFlow.Size.X + 5.ScaleInt(),
                    CS.Y - 54.ScaleInt() - ProfileFlow.Size.Y);
                Controls.Add(ProfileFlow);
            }
            else
            {
                Controls.Remove(ProfileFlow);
                ProfileFlow = null;
            }
            DrawFrame();
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
    }

    private GlobalSettingsMenu? gsm;

    private Task SettingOnClicked(IRenderObject arg)
    {
        if (gsm is null)
        {
            gsm = new GlobalSettingsMenu();
        }
        Controls.Add(gsm);
        Globals.ms.DrawFrame();
        return Task.CompletedTask;
    }
    
    public async Task LoadMainServer(MainServer Server)
    {
        
    }

    private Vector2i? p1, p2;

    protected override void OnKeyDown(KeyboardKeyEventArgs e)
    {
        base.OnKeyDown(e);
        if (e.Key == Keys.F9)
        {
            Globals.PrintParent(this);
        }
        else if (e.Key == Keys.F1)
        {
            p1 = new Vector2i((int)MousePosition.X, (int)MousePosition.Y);
            Console.WriteLine($"P1 set to: {p1.Value}");
        }
        else if (e.Key == Keys.F2)
        {
            p2 = new Vector2i((int)MousePosition.X, (int)MousePosition.Y);
            Console.WriteLine($"P2 set to: {p2.Value}");
        }
        else if (e.Key == Keys.F3)
        {
            if (p1 is null || p2 is null)
            {
                Console.WriteLine("P1 or P2 has not been set");
                return;
            }
            Vector2i size = p2.Value - p1.Value;
            CopyFromFrontToBack(p1.Value.X, p1.Value.Y, size.X, size.Y, (int)MousePosition.X, (int)MousePosition.Y);
            Console.WriteLine($"Buffer coppy");
        }
        else if (e.Key == Keys.F4)
        {
            if (!Context.IsCurrent) Context.MakeCurrent();
            Context.SwapBuffers();
            Console.WriteLine($"Force Swap");
        }
        else if (e.Key == Keys.F5)
        {
            ForceUpdate();
        }
        else if (e.Key == Keys.F9)
        {
            if (HoveringControl is IParent p)
            {
                Globals.PrintParent(p);
            }
            else
            {
                Globals.PrintParent(this);
            }
        }
        else if (e.Key == Keys.F10)
        {
            CheckParent(this);
        }
        else if (e.Key == Keys.F12)
        {
            Console.WriteLine("Update Time: " + UpdateAdverage);
            Console.WriteLine("Draw Time: " + DrawAdverage);
            Console.WriteLine("Total Time: " + TotalAdverage);
        }
    }

    private async Task<Task> LoginOnChangeToApp()
    {
        Controls.Clear();
        //ForceUpdate();
        BlockDraw = true;
        Title = "Luski";
        unsafe
        {
            GLFW.SetWindowSizeLimits(WindowPtr, 500.ScaleInt(), 250.ScaleInt(),GLFW.DontCare, GLFW.DontCare);
        }
        
        try
        {
            CenterWindow(Globals.Settings.Display);
        }
        catch (Exception e)
        {
            CenterWindow();
        }
        WindowBorder = WindowBorder.Resizable;
        BackgroundColor = new Color4(20, 20, 20, 255);

        Controls.Add(ServerFlow = new()
        {
            BackgroundColor = new(26, 26, 26, 255),
            Size = new(68.ScaleInt(), CS.Y),
            Anchor = ObjectAnchor.Top | ObjectAnchor.Left | ObjectAnchor.Bottom,
            Location = new(0)
        });
        ServerFlow.ForceDistanceUpdate(this);
        ServerFlow.LoadToParent(this,this);
        DrawFrame();

        
        ServerTitle = new()
        {
            Location = new(ServerFlow.Size.X, 0),
            Size = new(307.ScaleInt(), 46.ScaleInt()),
            BackgroundColor = new(30, 30, 30, 255)
        };
        Controls.Add(ServerTitle);


        ChannelSelector = new()
        {
            BackgroundColor = new(34, 34, 34, 255),
            Location = new(ServerFlow.Size.X, ServerTitle.Size.Y +2.ScaleInt()),
            Anchor = ObjectAnchor.Top | ObjectAnchor.Left | ObjectAnchor.Bottom
        };
        ChannelSelector.Size = new(ServerTitle.Size.X, CS.Y - 54.ScaleInt() - ChannelSelector.Location.Y);
        Controls.Add(ChannelSelector);
        ChannelSelector.ForceDistanceUpdate(this);
        
        Console.WriteLine("Waiting");
        Task.WhenAll(Globals.ServersLoading.ToArray()).Wait();
        Console.WriteLine("Done waiting");
        foreach (PublicServer pser in Globals.Luski.LoadedServers)
        {
            ServerIcon<PublicServer> si = new ServerIcon<PublicServer>(pser);
            ServerFlow.Controls.Add(si);
            si.LoadToParent(ServerFlow, this);
        }

        foreach (PublicServer pser in Globals.Luski.FailedServers)
        {
            Console.WriteLine(pser.Name);
            ServerIcon<PublicServer> si = new ServerIcon<PublicServer>(pser, true);
            ServerFlow.Controls.Add(si);
            si.LoadToParent(ServerFlow, this);
        }

        AddServerIcon asi = new();
        asi.Clicked += AddButtonClicked;
        ServerFlow.Controls.Add(asi);


        
        
        if (ServerFlow.Controls.Length > 1) (ServerFlow.Controls[0] as ServerIcon<PublicServer>)!.LoadServer().Start();
        DrawFrame();
        MainShow += OnMainShow;
        return Task.CompletedTask;
    }
    
    /*
    public override void ForceUpdate(bool resize = false)
    {
        DateTime dt = DateTime.Now;
        BlockDraw = true;
        for (int i = 0; i < Controls.Length; i++)
        {
            if (!Controls[i].Loaded) continue;
            bool top = (Controls[i].Anchor & ObjectAnchor.Top) == ObjectAnchor.Top;
            bool left = (Controls[i].Anchor & ObjectAnchor.Left) == ObjectAnchor.Left;
            bool right = (Controls[i].Anchor & ObjectAnchor.Right) == ObjectAnchor.Right;
            bool bottom = (Controls[i].Anchor & ObjectAnchor.Bottom) == ObjectAnchor.Bottom;
            if (!top && !bottom) { Controls[i].Anchor |= ObjectAnchor.Top; top = true; }
            if (!left && !right) { Controls[i].Anchor |= ObjectAnchor.Left; left = true; }

            int lx, ly, sy, sx;
            bool UpdateDistance = false, SizeChanged = false;
            if ((Controls[i].Anchor & ObjectAnchor.PreventWidthChange) == ObjectAnchor.PreventWidthChange)
            {
                UpdateDistance = true;
                lx = Controls[i].Location.X + ((CS.X - Controls[i].Distance.X - Controls[i].Size.X - Controls[i].Location.X) / 2);
                sx = Controls[i].Size.X;
            }
            else
            {
                SizeChanged = true;
                lx = (left ? Controls[i].Location.X : CS.X - Controls[i].Distance.X - Controls[i].Size.X);
                sx = (right ? CS.X - Controls[i].Distance.X - lx : Controls[i].Size.X);
            }
            if ((Controls[i].Anchor & ObjectAnchor.PreventHeightChange) == ObjectAnchor.PreventHeightChange)
            {
                ly = Controls[i].Location.Y + ((CS.Y - Controls[i].Distance.Y - Controls[i].Size.Y - Controls[i].Location.Y) / 2);
                sy = Controls[i].Size.Y;
            }
            else
            {
                ly = (top ? Controls[i].Location.Y : CS.Y - Controls[i].Distance.Y - Controls[i].Size.Y);
                sy = (bottom ? CS.Y - Controls[i].Distance.Y - ly : Controls[i].Size.Y);
            }

            if (Controls[i].Size.X != sx && Controls[i].Size.Y != sy)
            {
                SizeChanged = true;
            }
            Controls[i].SetSize(sx, sy);
            Controls[i].SetLocation(lx, ly);
            if (UpdateDistance)
            {
                Controls[i].ForceDistanceUpdate(this);
            }
            if (Controls[i] is IParent parent && SizeChanged)
            {
                parent.ParentResize();
            }
        }
        if (UpdateAdverage is null) UpdateAdverage = DateTime.Now - dt;
        else
        {
            UpdateAdverage = new((UpdateAdverage.Value.Ticks + (DateTime.Now - dt).Ticks)/2);
        }
        DateTime dtt = DateTime.Now;
        if (resize) ResizeFrameP1();
        else FrameP1();
        CheckParent(this);
        if (DrawAdverage is null || TotalAdverage is null)
        {
            DrawAdverage = DateTime.Now - dtt;
            TotalAdverage = DateTime.Now - dt;
        }
        else
        {
            DrawAdverage = new((DrawAdverage.Value.Ticks + (DateTime.Now - dtt).Ticks)/2);
            TotalAdverage = new((TotalAdverage.Value.Ticks + (DateTime.Now - dt).Ticks)/2);
        }
        BlockDraw = false;
    }
    */

    private TimeSpan? UpdateAdverage, DrawAdverage, TotalAdverage;
    
    
    private Task AddButtonClicked(IRenderObject arg)
    {
        CenterFullScreenBase aso = new(new AddServerOverlayForm())
        {
            AllowHoverFromBehind = false
        };
        //AddServerOverlayld aso = new();
        aso.Clicked += AsoOnClicked;
        Controls.Add(aso);
        
        aso.LoadToParent(this, this);
        GL.Scissor(0,0, CS.X, CS.Y);
        aso.Draw(0,0,0,0, CS.X, CS.Y);
        return Task.CompletedTask;
        
    }

    private Task AsoOnClicked(IRenderObject arg)
    {
        Globals.ms.Controls.Remove(arg);
        Globals.ms.DrawFrame();
        CenterFullScreenBase aso = (arg as CenterFullScreenBase)!;
        //AddServerOverlayld aso = (arg as AddServerOverlayld)!;
        aso.Clicked -= AsoOnClicked;
        aso.Clean();
        aso = null!;
        return Task.CompletedTask;
    }

    private Task OnMainShow()
    {
        if (Globals.Luski.MainServer is not null && Globals.Luski.MainServer.IsLogedIn)
        {
            Globals.Luski.MainServer.OnError += LuskiOnOnError;
        }

        return Task.CompletedTask;
    }

    public event Func<Task>? MainShow;

    private Task LuskiOnOnError(Exception arg)
    {
        Console.WriteLine(arg);
        return Task.CompletedTask;
    }

}