import 'dart:math';

import 'package:flutter/material.dart';

import 'package:jeweled/models/game_cell.dart';
import 'package:jeweled/models/game.dart';
import 'package:jeweled/models/cell_location.dart';
import 'package:jeweled/utils/color_theme.dart';

class GameBoardPainter extends CustomPainter {
  const GameBoardPainter(this.currentGame);

  final Game currentGame;

  static const drawTextValue = false;

  @override
  void paint(Canvas canvas, Size size) {
    final int sizeHorizontal = currentGame.settings.boardSize;
    final int sizeVertical = currentGame.settings.boardSize;

    final List cells = currentGame.board.cells;
    final double cellSize = size.width / max(sizeHorizontal, sizeVertical);

    // background
    for (var row = 0; row < sizeVertical; row++) {
      final double y = cellSize * row;
      for (var col = 0; col < sizeHorizontal; col++) {
        final double x = cellSize * col;

        final GameCell cell = cells[row][col];
        final int colorCode = ColorTheme.getColorCode(cell.value);

        final cellPaintBackground = Paint();
        cellPaintBackground.color = Color(colorCode);
        cellPaintBackground.style = PaintingStyle.fill;

        final Rect cellBackground =
            Rect.fromPoints(Offset(x - 1, y - 1), Offset(x + cellSize + 2, y + cellSize + 2));

        canvas.drawRect(cellBackground, cellPaintBackground);

        // draw value on cell
        if (drawTextValue) {
          final textPainter = TextPainter(
            text: TextSpan(
              text: cell.value.toString(),
              style: const TextStyle(
                color: Colors.black,
                fontSize: 15,
              ),
            ),
            textDirection: TextDirection.ltr,
          )..layout(
              minWidth: 0,
              maxWidth: size.width,
            );
          textPainter.paint(canvas, Offset(x + 4, y + 2));
        }
      }
    }

    // borders
    const double borderSize = 4;
    final cellPaintBorder = Paint();
    cellPaintBorder.color = ColorTheme.getBorderColor();
    cellPaintBorder.strokeWidth = borderSize;
    cellPaintBorder.strokeCap = StrokeCap.round;

    for (var row = 0; row < sizeVertical; row++) {
      final double y = cellSize * row;
      for (var col = 0; col < sizeHorizontal; col++) {
        final double x = cellSize * col;

        final GameCell cell = cells[row][col];
        final int? cellValue = cell.value;

        // top border
        if ((row == 0) ||
            (row > 1 &&
                cellValue != currentGame.getCellValue(CellLocation.go(row - 1, col)))) {
          final Offset borderStart = Offset(x, y);
          final Offset borderStop = Offset(x + cellSize, y);
          canvas.drawLine(borderStart, borderStop, cellPaintBorder);
        }

        // bottom border
        if ((row == sizeVertical - 1) ||
            ((row + 1) < sizeVertical &&
                cellValue != currentGame.getCellValue(CellLocation.go(row + 1, col)))) {
          final Offset borderStart = Offset(x, y + cellSize);
          final Offset borderStop = Offset(x + cellSize, y + cellSize);
          canvas.drawLine(borderStart, borderStop, cellPaintBorder);
        }

        // left border
        if ((col == 0) ||
            (col > 1 &&
                cellValue != currentGame.getCellValue(CellLocation.go(row, col - 1)))) {
          final Offset borderStart = Offset(x, y);
          final Offset borderStop = Offset(x, y + cellSize);
          canvas.drawLine(borderStart, borderStop, cellPaintBorder);
        }

        // right border
        if ((col == sizeHorizontal - 1) ||
            ((col + 1) < sizeHorizontal &&
                cellValue != currentGame.getCellValue(CellLocation.go(row, col + 1)))) {
          final Offset borderStart = Offset(x + cellSize, y);
          final Offset borderStop = Offset(x + cellSize, y + cellSize);
          canvas.drawLine(borderStart, borderStop, cellPaintBorder);
        }
      }
    }
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return false;
  }
}