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

namespace TraceCad.App.Tools;

public sealed class CalibrationLineTool(Action<Point2, Point2> applyMeasurement) : ISketchTool
{
    private Point2? _start;
    private Point2? _current;

    public string Name => "Calibrate 30";

    public string Prompt => _start is null
        ? "30 mm Calibration: click one end of the bold 30 mm line"
        : "30 mm Calibration: click the other end of the bold 30 mm line";

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

        var start = _start.Value;
        applyMeasurement(start, modelPoint);
        context.SetStatus($"30 mm Calibration: measured {start.DistanceTo(modelPoint):0.###} mm");
        _start = null;
        _current = null;
        context.Invalidate();
    }

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

        _current = modelPoint;
        context.SetStatus($"30 mm Calibration: current length {_start.Value.DistanceTo(modelPoint):0.###} mm");
        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 null)
        {
            return;
        }

        ToolDrawing.DrawPointMarker(context, renderContext.Transform, _current.Value);
        context.DrawLine(
            ToolDrawing.PreviewPen,
            renderContext.Transform.ModelToScreen(_start.Value),
            renderContext.Transform.ModelToScreen(_current.Value));
    }
}
