using Engine.Input;
using OpenTK.Mathematics;

namespace DoomDeathmatch.Component.UI;

public class UiComponent : Engine.Scene.Component.Component
{
  public UiContainerComponent? Container { get; set; }
  public Anchor Anchor { get; set; } = Anchor.Center;
  public Vector2 Offset { get; set; } = Vector2.Zero;
  public Anchor Center { get; set; } = Anchor.Center;

  public event Action<UiComponent>? OnClick;
  public event Action<UiComponent>? OnMouseOver;

  private readonly IInputHandler _inputHandler = Engine.Engine.Instance.InputHandler!;

  public override void Update(double parDeltaTime)
  {
    if (Container == null)
    {
      return;
    }

    var size = GameObject.Transform.Size * GameObject.Transform.Scale;
    GameObject.Transform.Translation.Xy = GetAnchorPosition(Container.GameObject.Transform.Size.Xy, Anchor) + Offset -
                                          GetAnchorPosition(size.Xy, Center);

    var transformMatrix = GameObject.Transform.FullTransformMatrix;
    var actualSize = transformMatrix.ExtractScale();
    var translation = transformMatrix.ExtractTranslation();

    var relativeMousePosition = Container.MousePosition.Xy - translation.Xy;

    if (Math.Abs(relativeMousePosition.X) <= actualSize.X / 2 && Math.Abs(relativeMousePosition.Y) <= actualSize.Y / 2)
    {
      OnMouseOver?.Invoke(this);

      if (_inputHandler.IsMouseButtonJustPressed(MouseButtonCode.Left))
      {
        OnClick?.Invoke(this);
      }
    }
  }

  public void InvokeClick()
  {
    OnClick?.Invoke(this);
  }

  private static Vector2 GetAnchorPosition(Vector2 parSize, Anchor parAnchor)
  {
    return parSize * GetAnchorRatio(parAnchor);
  }

  private static Vector2 GetAnchorRatio(Anchor parAnchor)
  {
    return parAnchor switch
    {
      Anchor.TopLeft => new Vector2(-0.5f, 0.5f),
      Anchor.TopCenter => new Vector2(0, 0.5f),
      Anchor.TopRight => new Vector2(0.5f, 0.5f),
      Anchor.CenterLeft => new Vector2(-0.5f, 0),
      Anchor.Center => new Vector2(0, 0),
      Anchor.CenterRight => new Vector2(0.5f, 0),
      Anchor.BottomLeft => new Vector2(-0.5f, -0.5f),
      Anchor.BottomCenter => new Vector2(0, -0.5f),
      Anchor.BottomRight => new Vector2(0.5f, -0.5f),
      _ => throw new ArgumentOutOfRangeException(nameof(parAnchor), parAnchor, null)
    };
  }
}