import 'package:flutter/material.dart';

import 'drawing_controller.dart';
import 'drawing_line.dart';

/// Custom painter that renders drawing lines on a canvas.
///
/// Converts normalized coordinates (0-1) to actual canvas coordinates
/// based on the provided canvas size.
class DrawingPainter extends CustomPainter {
  final List<DrawingLine> lines;
  final DrawingLine? currentLine;
  final Size canvasSize;

  DrawingPainter({
    required this.lines,
    required this.currentLine,
    required this.canvasSize,
  });

  @override
  void paint(Canvas canvas, Size size) {
    // Draw all completed lines
    for (final line in lines) {
      _drawLine(canvas, line);
    }

    // Draw the current line being drawn
    if (currentLine != null) {
      _drawLine(canvas, currentLine!);
    }
  }

  void _drawLine(Canvas canvas, DrawingLine line) {
    if (line.points.length < 2) return;

    final paint = Paint()
      ..color = line.color
      ..strokeWidth = line.strokeWidth * canvasSize.width
      ..strokeCap = StrokeCap.round
      ..strokeJoin = StrokeJoin.round
      ..style = PaintingStyle.stroke
      ..isAntiAlias = true;

    // Create path from normalized points
    final path = Path();
    final firstPoint = _toCanvasPoint(line.points.first);
    path.moveTo(firstPoint.dx, firstPoint.dy);

    // Use quadratic bezier curves for smooth lines
    if (line.points.length == 2) {
      final endPoint = _toCanvasPoint(line.points.last);
      path.lineTo(endPoint.dx, endPoint.dy);
    } else {
      for (int i = 1; i < line.points.length - 1; i++) {
        final p0 = _toCanvasPoint(line.points[i]);
        final p1 = _toCanvasPoint(line.points[i + 1]);
        final midPoint = Offset((p0.dx + p1.dx) / 2, (p0.dy + p1.dy) / 2);
        path.quadraticBezierTo(p0.dx, p0.dy, midPoint.dx, midPoint.dy);
      }
      // Draw to the last point
      final lastPoint = _toCanvasPoint(line.points.last);
      path.lineTo(lastPoint.dx, lastPoint.dy);
    }

    canvas.drawPath(path, paint);
  }

  /// Converts a normalized point (0-1) to canvas coordinates.
  Offset _toCanvasPoint(Offset normalizedPoint) {
    return Offset(
      normalizedPoint.dx * canvasSize.width,
      normalizedPoint.dy * canvasSize.height,
    );
  }

  @override
  bool shouldRepaint(covariant DrawingPainter oldDelegate) {
    return lines != oldDelegate.lines ||
        currentLine != oldDelegate.currentLine ||
        canvasSize != oldDelegate.canvasSize;
  }
}

/// A widget that displays drawing lines on a transparent canvas.
///
/// This widget only shows the drawings, it doesn't handle input.
/// Use [DrawingCanvas] or [DrawingBoard] for input handling.
class DrawingOverlay extends StatelessWidget {
  final DrawingController controller;
  final Size canvasSize;

  const DrawingOverlay({
    super.key,
    required this.controller,
    required this.canvasSize,
  });

  @override
  Widget build(BuildContext context) {
    return ListenableBuilder(
      listenable: controller,
      builder: (context, _) {
        return CustomPaint(
          size: canvasSize,
          painter: DrawingPainter(
            lines: controller.lines,
            currentLine: controller.currentLine,
            canvasSize: canvasSize,
          ),
        );
      },
    );
  }
}
