using GraphicsManager.Interfaces;
using GraphicsManager.Objects;
using OpenTK.Mathematics;

namespace Luski.GUI.MainScreen.UI.LuskiControls;

public class CompressedFlow : UserControl
{
    public CompressedFlow()
    {
        Controls.ControlAfterAdded += ControlsOnControlAdded;
        Controls.ControlRemoved += ControlsOnControlRemoved;
        SizeChanged += OnSizeChanged;
        Padding = new(5.ScaleInt());
        ChildPadding = new(Padding.X);
    }

    public event Func<IRenderObject, Task>? SizeUpdateNotIgnored; 

    public Vector4i Padding { get; set; }
    public Vector2i ChildPadding { get; set; }

    private bool IgnoreNextSizeChange;

    private Task OnSizeChanged(IRenderObject arg)
    {
        if (IgnoreNextSizeChange)
        {
            IgnoreNextSizeChange = false;
            return Task.CompletedTask;
        }
        UpdateControlesFromIndex(0);
        return Task.CompletedTask;
    }

    private Task ControlsOnControlRemoved()
    {
        UpdateControlesFromIndex(0);
        return Task.CompletedTask;
    }
    
    private Task ControlsOnControlAdded(int arg1, IRenderObject arg2)
    {
        if (arg1 != 0)
        {
            if (arg1 + 1 < Controls.Length)arg2.Location = Controls[arg1 + 1].Location;
        }
        else
        {
            arg2.Location = new(Padding.X, Padding.Y);
        }
        UpdateControlesFromIndex(arg1);
        return Task.CompletedTask;
    }

    private void UpdateControlesFromIndex(int index)
    {
        if (Controls.Length == 0)
        {
            IgnoreNextSizeChange = true;
            Size = new(Size.X, 0);
            if (SizeUpdateNotIgnored is not null) _ = SizeUpdateNotIgnored.Invoke(this);
            return;
        }
        if (index == 0) index++;
        for (int i = index; i < Controls.Length; i++)
        {
            if (Controls[i-1].Location.X + Controls[i-1].Size.X + Padding.Z + Controls[i].Size.X + ChildPadding.X > Size.X)
            {
                Controls[i].Location = new(Padding.X,
                    Controls[i - 1].Location.Y + Controls[i - 1].Size.Y + ChildPadding.Y);
            }
            else
            {
                Controls[i].Location = new(ChildPadding.X + Controls[i - 1].Location.X + Controls[i - 1].Size.X,
                    Controls[i - 1].Location.Y);
            }
        }

        if (Controls[Controls.Length - 1].Location.Y + Controls[Controls.Length - 1].Size.Y + Padding.W != Size.Y)
        {
            IgnoreNextSizeChange = true;
            Size = new(Size.X,
                Controls[Controls.Length - 1].Location.Y + Controls[Controls.Length - 1].Size.Y + Padding.W);
            if (SizeUpdateNotIgnored is not null) _ = SizeUpdateNotIgnored.Invoke(this);
        }
    }
}