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

import 'package:random/cubit/activity/activity_cubit.dart';
import 'package:random/models/activity/activity.dart';
import 'package:random/models/settings/settings_activity.dart';
import 'package:random/ui/painters/cell_painter.dart';
import 'package:random/ui/widgets/game/game_score.dart';

class GameBoardWidget extends StatefulWidget {
  const GameBoardWidget({
    super.key,
    required this.activity,
    required this.widgetSize,
  });

  final Activity activity;
  final Size widgetSize;

  @override
  State<GameBoardWidget> createState() => _GameBoardWidget();
}

class _GameBoardWidget extends State<GameBoardWidget> with TickerProviderStateMixin {
  List<List<Animation<double>?>> animations = [];

  void resetAnimations(ActivitySettings activitySettings) {
    final int boardSize = activitySettings.boardSizeValue;

    animations = List.generate(
      boardSize,
      (i) => List.generate(
        boardSize,
        (i) => null,
      ),
    );
  }

  void removeCell(BuildContext context, int x, int y) {
    final ActivityCubit activityCubit = BlocProvider.of<ActivityCubit>(context);
    final Activity updatedGame = activityCubit.state.currentActivity;

    // "remove" cell, update counters
    updatedGame.increaseScore(updatedGame.getCellValue(x, y));
    updatedGame.increaseMovesCount();
    updatedGame.updateCellValue(x, y, null);
    setState(() {});

    // "move down" cells
    final controller = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 750),
    )..addListener(() {
        if (mounted) {
          setState(() {});
        }
      });

    if (mounted) {
      setState(() {});
    }

    Animation<double> animation = Tween(
      begin: 0.0,
      end: 1.0,
    ).animate(CurvedAnimation(
      curve: Curves.bounceOut,
      parent: controller,
    ))
      ..addStatusListener((status) {
        if (status == AnimationStatus.completed) {
          // Update cell values
          for (var i = 0; i < y; i++) {
            updatedGame.updateCellValue(x, (y - i), updatedGame.getCellValue(x, (y - i) - 1));
          }
          updatedGame.setRandomCellValue(x, 0, updatedGame.activitySettings);

          resetAnimations(updatedGame.activitySettings);
          setState(() {});

          controller.dispose();
        }
      });

    for (var i = 0; i < y; i++) {
      animations[(y - i) - 1][x] = animation;
    }

    controller.forward().orCancel;
  }

  Widget buildBoard() {
    final double widgetWidth = widget.widgetSize.width;
    final double widgetHeight = widget.widgetSize.height;

    final int rowsCount = widget.activity.activitySettings.boardSizeValue;
    final int columnsCount = widget.activity.activitySettings.boardSizeValue;

    final double cellWidth = widgetWidth / columnsCount;
    final double cellHeight = widgetHeight / rowsCount;

    if (animations.isEmpty) {
      resetAnimations(widget.activity.activitySettings);
    }

    final List<Widget> cells = [];

    for (var y = 0; y < rowsCount; y++) {
      for (var x = 0; x < columnsCount; x++) {
        final int? value = widget.activity.getCellValue(x, y);

        if (value != null) {
          final Animation<double>? translation = animations[y][x];

          final Widget cellContent = CustomPaint(
            size: Size(cellWidth, cellHeight),
            willChange: false,
            painter: CellPainter(value: value),
          );

          final Widget cellWidget = Positioned(
            left: (x * cellWidth).toDouble(),
            top: ((y + (translation?.value ?? 0)) * cellHeight).toDouble(),
            child: SizedBox(
              width: cellWidth,
              height: cellHeight,
              child: cellContent,
            ),
          );

          cells.add(cellWidget);
        }
      }
    }

    return Container(
      width: widgetWidth,
      height: widgetHeight,
      color: Colors.black,
      child: Stack(
        children: cells,
      ),
    );
  }

  Widget interactiveBoard(BuildContext context) {
    final double widgetWidth = widget.widgetSize.width;
    final double widgetHeight = widget.widgetSize.height;

    final int rowsCount = widget.activity.activitySettings.boardSizeValue;
    final int columnsCount = widget.activity.activitySettings.boardSizeValue;

    return GestureDetector(
      child: buildBoard(),
      onTapUp: (details) {
        bool canRemoveCell = true;
        for (var row in animations) {
          for (var cell in row) {
            if (cell != null) {
              canRemoveCell = false;
            }
          }
        }

        if (canRemoveCell) {
          double xTap = details.localPosition.dx;
          double yTap = details.localPosition.dy;

          int x = (xTap / widgetWidth * columnsCount).toInt();
          int y = (yTap / widgetHeight * rowsCount).toInt();
          printlog('[$x,$y]');

          removeCell(context, x, y);
        } else {
          printlog('animation in progress...');
        }
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        interactiveBoard(context),
        GameScoreWidget(activity: widget.activity),
      ],
    );
  }
}