using System;
using System.Numerics;
using System.Threading;

namespace LightlessSync.UI;

internal static class ProfileEditorLayoutCoordinator
{
    private static readonly Lock Gate = new();
    private static string? _activeUid;
    private static Vector2? _anchor;

    private const float ProfileWidth = 840f;
    private const float ProfileHeight = 525f;
    private const float EditorWidth = 380f;
    private const float Spacing = 0f;
    private static readonly Vector2 DefaultOffset = new(50f, 70f);

    public static void Enable(string uid)
    {
        using var _ = Gate.EnterScope();
        if (!string.Equals(_activeUid, uid, StringComparison.Ordinal))
            _anchor = null;
        _activeUid = uid;
    }

    public static void Disable(string uid)
    {
        using var _ = Gate.EnterScope();
        if (string.Equals(_activeUid, uid, StringComparison.Ordinal))
        {
            _activeUid = null;
            _anchor = null;
        }
    }

    public static bool IsActive(string uid)
    {
        using var _ = Gate.EnterScope();
        return string.Equals(_activeUid, uid, StringComparison.Ordinal);
    }

    public static Vector2 GetProfileSize(float scale) => new(ProfileWidth * scale, ProfileHeight * scale);
    public static Vector2 GetEditorSize(float scale) => new(EditorWidth * scale, ProfileHeight * scale);

    public static Vector2 GetEditorOffset(float scale) => new((ProfileWidth + Spacing) * scale, 0f);

    public static Vector2 EnsureAnchor(Vector2 viewportOrigin, float scale)
    {
        using var _ = Gate.EnterScope();
        if (_anchor is null)
            _anchor = viewportOrigin + DefaultOffset * scale;
        return _anchor.Value;
    }

    public static void UpdateAnchorFromProfile(Vector2 profilePosition)
    {
        using var _ = Gate.EnterScope();
        _anchor = profilePosition;
    }

    public static void UpdateAnchorFromEditor(Vector2 editorPosition, float scale)
    {
        using var _ = Gate.EnterScope();
        _anchor = editorPosition - GetEditorOffset(scale);
    }

    public static Vector2 GetProfilePosition(float scale)
    {
        using var _ = Gate.EnterScope();
        return _anchor ?? Vector2.Zero;
    }

    public static Vector2 GetEditorPosition(float scale)
    {
        using var _ = Gate.EnterScope();
        return (_anchor ?? Vector2.Zero) + GetEditorOffset(scale);
    }

    public static bool NearlyEquals(Vector2 current, Vector2 target, float epsilon = 0.5f)
    {
        return MathF.Abs(current.X - target.X) <= epsilon && MathF.Abs(current.Y - target.Y) <= epsilon;
    }
}
