import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';

import 'package:solitaire/config/default_game_settings.dart';
import 'package:solitaire/data/game_data.dart';
import 'package:solitaire/models/game/board.dart';
import 'package:solitaire/models/game/cell.dart';
import 'package:solitaire/models/game/cell_location.dart';
import 'package:solitaire/models/settings/settings_game.dart';
import 'package:solitaire/models/settings/settings_global.dart';

class ParameterPainter extends CustomPainter {
  const ParameterPainter({
    required this.code,
    required this.value,
    required this.gameSettings,
    required this.globalSettings,
  });

  final String code;
  final String value;
  final GameSettings gameSettings;
  final GlobalSettings globalSettings;

  @override
  void paint(Canvas canvas, Size size) {
    // force square
    final double canvasSize = min(size.width, size.height);

    // content
    switch (code) {
      case DefaultGameSettings.parameterCodeLayout:
        paintLayoutParameterItem(canvas, canvasSize);
        break;
      default:
        printlog('Unknown parameter: $code/$value');
        paintUnknownParameterItem(canvas, canvasSize);
    }
  }

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

  // "unknown" parameter -> simple block with text
  void paintUnknownParameterItem(
    final Canvas canvas,
    final double size,
  ) {
    final paint = Paint();
    paint.strokeJoin = StrokeJoin.round;
    paint.strokeWidth = 3;

    final textSpan = TextSpan(
      text: '$code\n$value',
      style: const TextStyle(
        color: Colors.black,
        fontSize: 18,
        fontWeight: FontWeight.bold,
      ),
    );
    final textPainter = TextPainter(
      text: textSpan,
      textDirection: TextDirection.ltr,
      textAlign: TextAlign.center,
    );
    textPainter.layout();
    textPainter.paint(
      canvas,
      Offset(
        (size - textPainter.width) * 0.5,
        (size - textPainter.height) * 0.5,
      ),
    );
  }

  void paintLayoutParameterItem(
    final Canvas canvas,
    final double size,
  ) {
    {
      Color gridBackgroundColor = Colors.grey;

      switch (value) {
        case DefaultGameSettings.layoutValueFrench:
          gridBackgroundColor = Colors.green;
          break;
        case DefaultGameSettings.layoutValueGerman:
          gridBackgroundColor = Colors.orange;
          break;
        case DefaultGameSettings.layoutValueEnglish:
          gridBackgroundColor = Colors.red;
          break;
        case DefaultGameSettings.layoutValueDiamond:
          gridBackgroundColor = Colors.purple;
          break;
        default:
          printlog('Wrong value for size parameter value: $value');
      }

      final paint = Paint();
      paint.strokeJoin = StrokeJoin.round;
      paint.strokeWidth = 3;

      // Mini grid
      final borderColor = Colors.grey.shade800;

      // Get board data from named templates
      final List<String>? template = GameData.templates[value];
      final BoardCells grid = [];

      int row = 0;
      template?.forEach((String line) {
        final List<Cell> gridLine = [];
        int col = 0;
        line.split("").forEach((String tileCode) {
          gridLine.add(tileCode == ' '
              ? Cell.none
              : Cell(
                  location: CellLocation.go(row, col),
                  hasHole: true,
                  hasPeg: (tileCode == 'o'),
                ));
          col++;
        });
        row++;
        grid.add(gridLine);
      });

      final int gridWidth = grid.length;
      final int gridHeight = grid.first.length;
      paint.strokeWidth = 2;

      final double cellSize = (size * .9) / max(gridWidth, gridHeight);
      final double originX = (size - gridWidth * cellSize) / 2;
      final double originY = (size - gridHeight * cellSize) / 2;

      for (int row = 0; row < gridHeight; row++) {
        for (int col = 0; col < gridWidth; col++) {
          final Offset topLeft = Offset(originX + col * cellSize, originY + row * cellSize);
          final Offset bottomRight = topLeft + Offset(cellSize, cellSize);

          paint.color = Colors.white;
          paint.style = PaintingStyle.fill;

          if (grid[row][col].hasPeg) {
            paint.color = gridBackgroundColor;
            canvas.drawRect(Rect.fromPoints(topLeft, bottomRight), paint);
          }
          if (grid[row][col].hasHole) {
            paint.color = borderColor;
            paint.style = PaintingStyle.stroke;
            canvas.drawRect(Rect.fromPoints(topLeft, bottomRight), paint);
          }
        }
      }
    }
  }
}