using Avalonia.Input;
using Avalonia.Media;
using TraceCad.Core.Geometry;

namespace TraceCad.App.Tools;

public sealed class MeasureTool : ISketchTool
{
    private Point2? _start;
    private Point2? _current;

    public string Name => "Measure";

    public string Prompt => _start is null
        ? "Measure: choose first point"
        : "Measure: choose second point";

    public void PointerDown(ToolContext context, Point2 modelPoint)
    {
        var point = context.Snap(modelPoint);
        if (_start is null)
        {
            _start = point;
            _current = point;
            context.SetStatus(Prompt);
            context.Invalidate();
            return;
        }

        _current = point;
        context.SetStatus(FormatMeasurement(_start.Value, point));
        _start = null;
        _current = null;
        context.Invalidate();
    }

    public void PointerMove(ToolContext context, Point2 modelPoint)
    {
        if (_start is null)
        {
            return;
        }

        _current = context.Snap(modelPoint);
        context.SetStatus(FormatMeasurement(_start.Value, _current.Value));
        context.Invalidate();
    }

    public void PointerUp(ToolContext context, Point2 modelPoint)
    {
    }

    public void KeyDown(ToolContext context, Key key)
    {
    }

    public void Cancel(ToolContext context)
    {
        _start = null;
        _current = null;
        context.SetStatus(Prompt);
        context.Invalidate();
    }

    public void RenderOverlay(DrawingContext context, ToolRenderContext renderContext)
    {
        if (_start is null)
        {
            return;
        }

        ToolDrawing.DrawPointMarker(context, renderContext.Transform, _start.Value);
        if (_current is not null)
        {
            ToolDrawing.DrawPointMarker(context, renderContext.Transform, _current.Value);
            context.DrawLine(
                ToolDrawing.PreviewPen,
                renderContext.Transform.ModelToScreen(_start.Value),
                renderContext.Transform.ModelToScreen(_current.Value));
        }
    }

    private static string FormatMeasurement(Point2 start, Point2 end)
    {
        var delta = end - start;
        var angle = Math.Atan2(delta.Y, delta.X) * 180.0 / Math.PI;
        return $"Measure: length {delta.Length:0.###} mm   dx {delta.X:0.###} mm   dy {delta.Y:0.###} mm   angle {angle:0.##} deg";
    }
}
