// lib/editor/canvas/note_background.dart
//
// rnote-style page background TEMPLATES for the blank-note editor. A background
// is a repeating PATTERN painted in the note page's local pixel space (the
// `pageWidget` is sized to the page rect inside the InteractiveViewer, so a
// CustomPainter here scales 1:1 with zoom — no extra transform needed).
//
// The choice is per-notebook and persists in the sidecar (stored as the enum
// `name`; missing/unknown → [NoteBackground.blank] for back-compat).

import 'package:flutter/material.dart';

/// The available page-background templates (rnote: blank + dots/lines/grid +
/// the Cornell note layout).
enum NoteBackground {
  /// Plain white sheet, no pattern.
  blank,

  /// A regular grid of small dots (dotted paper).
  dots,

  /// Evenly spaced horizontal lines (ruled / lined paper).
  ruled,

  /// Square grid (graph paper).
  grid,

  /// Cornell layout: a left cue-column line + a bottom summary line over a
  /// ruled note-taking body.
  cornell,
}

/// Decode a persisted background name (the enum [NoteBackground.name]); unknown
/// or missing values fall back to [NoteBackground.blank] (back-compat).
NoteBackground noteBackgroundFromName(String? name) {
  for (final b in NoteBackground.values) {
    if (b.name == name) return b;
  }
  return NoteBackground.blank;
}

/// Localized-ish English display label for the picker menu.
String noteBackgroundLabel(NoteBackground b) {
  switch (b) {
    case NoteBackground.blank:
      return 'Blank';
    case NoteBackground.dots:
      return 'Dots';
    case NoteBackground.ruled:
      return 'Ruled lines';
    case NoteBackground.grid:
      return 'Grid';
    case NoteBackground.cornell:
      return 'Cornell';
  }
}

/// An icon for the picker menu.
IconData noteBackgroundIcon(NoteBackground b) {
  switch (b) {
    case NoteBackground.blank:
      return Icons.crop_portrait;
    case NoteBackground.dots:
      return Icons.grain;
    case NoteBackground.ruled:
      return Icons.notes;
    case NoteBackground.grid:
      return Icons.grid_4x4;
    case NoteBackground.cornell:
      return Icons.view_quilt_outlined;
  }
}

/// Paints a [NoteBackground] template behind the ink, in the page's local pixel
/// space. Spacing is page-relative (a fraction of page width) so the template
/// looks the same on any logical page size, and the lines are a light, subtle
/// grey so they sit behind handwriting.
class NoteBackgroundPainter extends CustomPainter {
  const NoteBackgroundPainter(this.background);

  final NoteBackground background;

  /// Pattern spacing as a fraction of the page WIDTH — a ~28-line page.
  static const double _spacingFraction = 1 / 28;

  static const Color _lineColor = Color(0x1A000000); // ~10% black, subtle grey.
  static const Color _dotColor = Color(0x33000000); // dots a touch darker.
  static const Color _accentColor = Color(0x33335C81); // Cornell margin lines.

  @override
  void paint(Canvas canvas, Size size) {
    if (background == NoteBackground.blank) return;
    final spacing = size.width * _spacingFraction;
    if (spacing <= 0) return;

    switch (background) {
      case NoteBackground.blank:
        break;
      case NoteBackground.dots:
        _paintDots(canvas, size, spacing);
      case NoteBackground.ruled:
        _paintRuled(canvas, size, spacing);
      case NoteBackground.grid:
        _paintGrid(canvas, size, spacing);
      case NoteBackground.cornell:
        _paintCornell(canvas, size, spacing);
    }
  }

  void _paintDots(Canvas canvas, Size size, double spacing) {
    final paint = Paint()
      ..color = _dotColor
      ..style = PaintingStyle.fill;
    final r = (spacing * 0.06).clamp(0.6, 2.0);
    for (double y = spacing; y < size.height; y += spacing) {
      for (double x = spacing; x < size.width; x += spacing) {
        canvas.drawCircle(Offset(x, y), r, paint);
      }
    }
  }

  void _paintRuled(Canvas canvas, Size size, double spacing) {
    final paint = Paint()
      ..color = _lineColor
      ..strokeWidth = 1.0;
    for (double y = spacing; y < size.height; y += spacing) {
      canvas.drawLine(Offset(0, y), Offset(size.width, y), paint);
    }
  }

  void _paintGrid(Canvas canvas, Size size, double spacing) {
    final paint = Paint()
      ..color = _lineColor
      ..strokeWidth = 1.0;
    for (double y = spacing; y < size.height; y += spacing) {
      canvas.drawLine(Offset(0, y), Offset(size.width, y), paint);
    }
    for (double x = spacing; x < size.width; x += spacing) {
      canvas.drawLine(Offset(x, 0), Offset(x, size.height), paint);
    }
  }

  void _paintCornell(Canvas canvas, Size size, double spacing) {
    // Ruled body lines.
    _paintRuled(canvas, size, spacing);
    final accent = Paint()
      ..color = _accentColor
      ..strokeWidth = 1.4;
    // Left cue-column vertical line (~25% of width).
    final cueX = size.width * 0.25;
    // Bottom summary horizontal line (~80% down).
    final summaryY = size.height * 0.80;
    canvas.drawLine(Offset(cueX, 0), Offset(cueX, summaryY), accent);
    canvas.drawLine(Offset(0, summaryY), Offset(size.width, summaryY), accent);
  }

  @override
  bool shouldRepaint(covariant NoteBackgroundPainter oldDelegate) =>
      oldDelegate.background != background;
}
