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

import 'package:sudoku/cubit/game_cubit.dart';
import 'package:sudoku/models/game/cell.dart';
import 'package:sudoku/models/game/game.dart';

class CellWidget extends StatelessWidget {
  const CellWidget({super.key, required this.cell});

  final Cell cell;

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<GameCubit, GameState>(
      builder: (BuildContext context, GameState gameState) {
        final Game game = gameState.currentGame;

        final String imageAsset = getImageAssetName(game);

        return Container(
          decoration: BoxDecoration(
            color: getBackgroundColor(game),
            border: getCellBorders(game),
          ),
          child: GestureDetector(
            child: AnimatedSwitcher(
              duration: const Duration(milliseconds: 100),
              transitionBuilder: (Widget child, Animation<double> animation) {
                return ScaleTransition(scale: animation, child: child);
              },
              child: Image(
                image: AssetImage(imageAsset),
                fit: BoxFit.fill,
                key: ValueKey<int>(imageAsset.hashCode),
              ),
            ),
            onTap: () {
              final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);

              if (cell.location.col != game.selectedCell?.location.col ||
                  cell.location.row != game.selectedCell?.location.row) {
                gameCubit.selectCell(cell.location);
              } else {
                gameCubit.unselectCell();
              }
            },
          ),
        );
      },
    );
  }

  /*
  * Compute image asset name, from skin and cell value/state
  */
  String getImageAssetName(Game game) {
    if ((cell.value) > 0) {
      final int cellValue = game.getTranslatedValueForDisplay(cell.value);
      return 'assets/skins/${game.globalSettings.skin}_$cellValue.png';
    }

    return 'assets/ui/cell_empty.png';
  }

  // Compute cell background color, from cell state
  Color getBackgroundColor(Game game) {
    final Color editableCellColor = Colors.grey.shade100;
    final Color editableCellColorConflict = Colors.pink.shade100;
    final Color fixedCellColor = Colors.grey.shade300;
    final Color fixedCellColorConflict = Colors.pink.shade200;
    final Color editableSelectedValueColor = Colors.green.shade100;
    final Color fixedSelectedValueColor = Colors.green.shade300;
    final Color editableAnimated = Colors.green.shade200;
    final Color fixedAnimated = Colors.green.shade300;

    Color backgroundColor = editableCellColor;

    if (cell.isFixed == true) {
      backgroundColor = fixedCellColor;
    }

    final int conflictsCount = game.boardConflicts[cell.location.row][cell.location.col];

    if (game.showConflicts == true) {
      if (conflictsCount != 0) {
        if (cell.isFixed == true) {
          backgroundColor = fixedCellColorConflict;
        } else {
          backgroundColor = editableCellColorConflict;
        }
      }

      if ((cell.value != 0) && (cell.value == game.selectedCell?.value)) {
        if (cell.isFixed == true) {
          backgroundColor = fixedSelectedValueColor;
        } else {
          backgroundColor = editableSelectedValueColor;
        }
      }
    }

    final bool isAnimated = game.boardAnimated[cell.location.row][cell.location.col];

    if (isAnimated) {
      if (cell.isFixed == true) {
        backgroundColor = fixedAnimated;
      } else {
        backgroundColor = editableAnimated;
      }
    }

    return backgroundColor;
  }

  // Compute cell borders, from board size and cell state
  Border getCellBorders(Game game) {
    final Color cellBorderDarkColor = Colors.grey.shade800;
    final Color cellBorderLightColor = Colors.grey.shade600;
    const Color cellBorderSelectedColor = Colors.red;

    Color cellBorderColor = cellBorderSelectedColor;
    double cellBorderWidth = 4;

    // Reduce cell border width on big boards
    if (game.boardSize > 8) {
      cellBorderWidth = 2;
      if (game.boardSize > 10) {
        cellBorderWidth = 1;
      }
    }

    if (!game.isRunning) {
      cellBorderColor = Colors.green.shade700;
    }

    Border borders = Border.all(
      color: cellBorderColor,
      width: cellBorderWidth,
    );

    // Update cell borders if not currently selected cell
    if (cell.location.col != game.selectedCell?.location.col ||
        cell.location.row != game.selectedCell?.location.row) {
      borders = Border(
        top: BorderSide(
            width: cellBorderWidth,
            color: (((cell.location.row) % game.blockSizeVertical) == 0)
                ? cellBorderDarkColor
                : cellBorderLightColor),
        left: BorderSide(
            width: cellBorderWidth,
            color: (((cell.location.col) % game.blockSizeHorizontal) == 0)
                ? cellBorderDarkColor
                : cellBorderLightColor),
        right: BorderSide(
            width: cellBorderWidth,
            color: ((((cell.location.col) + 1) % game.blockSizeHorizontal) == 0)
                ? cellBorderDarkColor
                : cellBorderLightColor),
        bottom: BorderSide(
            width: cellBorderWidth,
            color: ((((cell.location.row) + 1) % game.blockSizeVertical) == 0)
                ? cellBorderDarkColor
                : cellBorderLightColor),
      );
    }

    return borders;
  }
}