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

import 'package:snake/models/activity/activity.dart';

part 'activity_state.dart';

class ActivityCubit extends HydratedCubit<ActivityState> {
  ActivityCubit()
      : super(ActivityState(
          currentActivity: Activity.createEmpty(),
        ));

  void updateState(Activity activity) {
    emit(ActivityState(
      currentActivity: activity,
    ));
  }

  void refresh() {
    final Activity activity = Activity(
      // Settings
      activitySettings: state.currentActivity.activitySettings,
      // State
      isRunning: state.currentActivity.isRunning,
      isStarted: state.currentActivity.isStarted,
      isFinished: state.currentActivity.isFinished,
      animationInProgress: state.currentActivity.animationInProgress,
      // Base data
      snake: state.currentActivity.snake,
      board: state.currentActivity.board,
      boardSize: state.currentActivity.boardSize,
      // Game data
      score: state.currentActivity.score,
      gameWon: state.currentActivity.gameWon,
    );
    // game.dump();

    updateState(activity);
  }

  void startNewActivity(BuildContext context) {
    final ActivitySettingsCubit activitySettingsCubit =
        BlocProvider.of<ActivitySettingsCubit>(context);

    final Activity newActivity = Activity.createNew(
      // Settings
      activitySettings: activitySettingsCubit.state.settings,
    );

    newActivity.dump();

    updateState(newActivity);
    updateGameIsRunning(true);

    startSnake();

    refresh();
  }

  bool canBeResumed() {
    return state.currentActivity.canBeResumed;
  }

  void quitActivity() {
    state.currentActivity.isRunning = false;
    refresh();
  }

  void resumeSavedActivity() {
    state.currentActivity.isRunning = true;
    refresh();
  }

  void deleteSavedActivity() {
    state.currentActivity.isRunning = false;
    state.currentActivity.isFinished = true;
    refresh();
  }

  void startSnake() async {
    int speed = 500;

    while (!state.currentActivity.isFinished && state.currentActivity.isRunning) {
      moveSnake();
      await Future.delayed(Duration(milliseconds: speed));

      // speed up
      speed -= 1;

      if (speed == 0) {
        state.currentActivity.isFinished = true;
        state.currentActivity.gameWon = true;
        refresh();
      }
    }
  }

  void turnLeft() {
    state.currentActivity.turnLeft();
    refresh();
  }

  void turnRight() {
    state.currentActivity.turnRight();
    refresh();
  }

  void moveSnake() {
    state.currentActivity.moveSnake();
    refresh();
  }

  void updateSnakeSize(int delta) {
    state.currentActivity.updateSnakeSize(delta);
    refresh();
  }

  void increaseScore() {
    state.currentActivity.score++;
    refresh();
  }

  void updateAnimationInProgress(bool inProgress) {
    state.currentActivity.animationInProgress = inProgress;
    refresh();
  }

  void updateGameIsRunning(bool gameIsRunning) {
    state.currentActivity.isRunning = gameIsRunning;
    refresh();
  }

  void updateGameIsStarted(bool gameIsStarted) {
    state.currentActivity.isStarted = gameIsStarted;
    refresh();
  }

  void updateGameIsFinished(bool gameIsFinished) {
    state.currentActivity.isFinished = gameIsFinished;
    refresh();
  }

  void updateGameWon(bool gameWon) {
    state.currentActivity.gameWon = gameWon;
    refresh();
  }

  @override
  ActivityState? fromJson(Map<String, dynamic> json) {
    final Activity currentActivity = json['currentActivity'] as Activity;

    return ActivityState(
      currentActivity: currentActivity,
    );
  }

  @override
  Map<String, dynamic>? toJson(ActivityState state) {
    return <String, dynamic>{
      'currentActivity': state.currentActivity,
    };
  }
}