import 'package:flutter/material.dart';

import 'package:minehunter/provider/data.dart';
import 'package:minehunter/utils/board_animate.dart';
import 'package:minehunter/utils/board_utils.dart';

class Cell {
  bool isMined = false;
  bool isExplored = false;
  bool isMarked = false;
  bool isExploded = false;
  int minesCountAround = 0;

  bool isAnimated = false;

  Cell(
    this.isMined,
  );

  /*
  * Build widget for board cell, with interactions
  */
  Container widget(Data myProvider, int row, int col) {
    String imageAsset = getImageAssetName(myProvider);

    return Container(
      decoration: BoxDecoration(
        color: getBackgroundColor(myProvider),
        border: getCellBorders(myProvider, row, col),
      ),
      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: () {
          // Set mines on board after first player try
          if (!myProvider.isBoardMined) {
            myProvider.updateCells(BoardUtils.createBoard(myProvider, row, col));
            myProvider.updateIsBoardMined(true);
          }

          if (!(myProvider.gameWin || myProvider.gameFail)) {
            if (myProvider.reportMode) {
              BoardUtils.reportCell(myProvider, row, col);
            } else {
              BoardUtils.walkOnCell(myProvider, row, col);
            }
            if (BoardUtils.checkGameIsFinished(myProvider)) {
              myProvider.updateReportMode(false);
              BoardAnimate.startAnimation(myProvider, myProvider.gameWin ? 'win' : 'fail');
            }
          }
        },
      ),
    );
  }

  /*
  * Compute image asset name, from skin and cell value/state
  */
  String getImageAssetName(Data myProvider) {
    String imageAsset = 'assets/skins/${myProvider.parameterSkin}_tile_unknown.png';

    bool showSolution = myProvider.gameWin || myProvider.gameFail;
    if (!showSolution) {
      // Running game
      if (isExplored) {
        if (isMined) {
          // Boom
          imageAsset = 'assets/skins/${myProvider.parameterSkin}_tile_mine.png';
        } else {
          // Show mines count around
          imageAsset = 'assets/skins/${myProvider.parameterSkin}_tile_$minesCountAround.png';
        }
      } else {
        if (isMarked) {
          // Danger!
          imageAsset = 'assets/skins/${myProvider.parameterSkin}_tile_flag.png';
        }
      }
    } else {
      // Finished game
      if (isMined) {
        if (isExploded) {
          // Mine exploded
          imageAsset = 'assets/skins/${myProvider.parameterSkin}_tile_mine.png';
        } else {
          // Mine not found
          imageAsset = 'assets/skins/${myProvider.parameterSkin}_tile_mine_not_found.png';
        }
      } else {
        // Show all mines counts
        imageAsset = 'assets/skins/${myProvider.parameterSkin}_tile_$minesCountAround.png';
      }
    }

    return imageAsset;
  }

  // Compute cell background color, from cell state
  Color getBackgroundColor(Data myProvider) {
    if (myProvider.gameWin) {
      return isAnimated ? Colors.green.shade400 : Colors.green.shade500;
    }
    if (myProvider.gameFail) {
      return isAnimated ? Colors.pink.shade200 : Colors.pink.shade400;
    }

    return isAnimated ? Colors.white : Colors.grey.shade200;
  }

  // Compute cell borders, from board size and cell state
  Border getCellBorders(Data myProvider, int row, int col) {
    Color cellBorderColor = Colors.grey.shade500;
    double cellBorderWidth = 4;

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

    if (myProvider.gameWin) {
      cellBorderColor = Colors.green.shade700;
    } else if (myProvider.gameFail) {
      cellBorderColor = Colors.pink.shade300;
    }

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

    return borders;
  }
}