import 'dart:ui' as ui;

import 'package:aves_model/aves_model.dart';
import 'package:flutter/material.dart';

class FixedExtentGridPainter extends CustomPainter {
  final TileLayout tileLayout;
  final Offset tileCenter;
  final Size tileSize;
  final double spacing, horizontalPadding, borderWidth;
  final Radius borderRadius;
  final Color color;
  final TextDirection textDirection;

  const FixedExtentGridPainter({
    required this.tileLayout,
    required this.tileCenter,
    required this.tileSize,
    required this.spacing,
    required this.horizontalPadding,
    required this.borderWidth,
    required this.borderRadius,
    required this.color,
    required this.textDirection,
  });

  @override
  void paint(Canvas canvas, Size size) {
    late final Offset chipCenter;
    late final Size chipSize;
    late final int deltaColumn;
    late final Shader strokeShader;
    switch (tileLayout) {
      case TileLayout.mosaic:
        return;
      case TileLayout.grid:
        chipCenter = tileCenter;
        chipSize = tileSize;
        deltaColumn = 2;
        strokeShader = ui.Gradient.radial(
          tileCenter,
          chipSize.shortestSide * 2,
          [
            color,
            Colors.transparent,
          ],
          [
            .8,
            1,
          ],
        );
      case TileLayout.list:
        chipSize = Size.square(tileSize.shortestSide);
        final chipCenterToEdge = chipSize.width / 2;
        chipCenter = Offset(textDirection == TextDirection.rtl ? size.width - (chipCenterToEdge + horizontalPadding) : chipCenterToEdge + horizontalPadding, tileCenter.dy);
        deltaColumn = 0;
        strokeShader = ui.Gradient.linear(
          tileCenter - Offset(0, chipSize.shortestSide * 3),
          tileCenter + Offset(0, chipSize.shortestSide * 3),
          [
            Colors.transparent,
            color,
            color,
            Colors.transparent,
          ],
          [
            0,
            .2,
            .8,
            1,
          ],
        );
    }
    final strokePaint = Paint()
      ..style = PaintingStyle.stroke
      ..strokeWidth = borderWidth
      ..shader = strokeShader;
    final fillPaint = Paint()
      ..style = PaintingStyle.fill
      ..color = color.withValues(alpha: .25);

    final chipWidth = chipSize.width;
    final chipHeight = chipSize.height;

    final deltaX = tileSize.width + spacing;
    final deltaY = tileSize.height + spacing;
    for (var i = -deltaColumn; i <= deltaColumn; i++) {
      final dx = deltaX * i;
      for (var j = -2; j <= 2; j++) {
        if (i == 0 && j == 0) continue;
        final dy = deltaY * j;
        final rect = RRect.fromRectAndRadius(
          Rect.fromCenter(
            center: chipCenter + Offset(dx, dy),
            width: chipWidth - borderWidth,
            height: chipHeight - borderWidth,
          ),
          borderRadius,
        );

        if ((i.abs() == 1 && j == 0) || (j.abs() == 1 && i == 0)) {
          canvas.drawRRect(rect, fillPaint);
        }
        canvas.drawRRect(rect, strokePaint);
      }
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
