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

namespace TraceCad.App.Tools;

public sealed class Circle3PointTool : ISketchTool
{
    private readonly List<Point2> _points = new();
    private Point2? _current;

    public string Name => "Circle 3P";

    public string Prompt => _points.Count switch
    {
        0 => "Circle 3P: choose first point on circle",
        1 => "Circle 3P: choose second point on circle",
        _ => "Circle 3P: choose third point on circle"
    };

    public void PointerDown(ToolContext context, Point2 modelPoint)
    {
        _points.Add(context.Snap(modelPoint));

        if (_points.Count == 3)
        {
            if (GeometryHelpers.TryCreateCircleFromThreePoints(_points[0], _points[1], _points[2], out var circle))
            {
                context.Commands.Execute(
                    context.Document,
                    new AddEntityCommand(new CircleEntity(Guid.NewGuid(), Layer.Cut.Name, circle.Center, circle.Radius)));
                context.SetStatus("Circle 3P: circle created");
            }
            else
            {
                context.SetStatus("Circle 3P: points are collinear");
            }

            _points.Clear();
        }
        else
        {
            context.SetStatus(Prompt);
        }

        context.Invalidate();
    }

    public void PointerMove(ToolContext context, Point2 modelPoint)
    {
        _current = context.Snap(modelPoint);
        context.Invalidate();
    }

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

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

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

    public void RenderOverlay(DrawingContext context, ToolRenderContext renderContext)
    {
        foreach (var point in _points)
        {
            ToolDrawing.DrawPointMarker(context, renderContext.Transform, point);
        }

        if (_points.Count == 2 && _current is not null)
        {
            var pen = GeometryHelpers.TryCreateCircleFromThreePoints(_points[0], _points[1], _current.Value, out var circle)
                ? ToolDrawing.PreviewPen
                : ToolDrawing.InvalidPen;

            if (circle.Radius > GeometryConstants.Epsilon)
            {
                ToolDrawing.DrawCircle(context, renderContext.Transform, circle.Center, circle.Radius, pen);
            }
        }
    }
}
