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

import 'package:momomotus/config/application_config.dart';
import 'package:momomotus/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,
      animationInProgress: state.currentActivity.animationInProgress,
      // Base data
      word: state.currentActivity.word,
      dictionary: state.currentActivity.dictionary,
      // Game data
      currentGuess: state.currentActivity.currentGuess,
      foundLetters: state.currentActivity.foundLetters,
      guesses: state.currentActivity.guesses,
      foundWord: state.currentActivity.foundWord,
    );
    // 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);
    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;
    updateState(Activity.createEmpty());
    refresh();
  }

  void currentGuessAddLetter(String letter) {
    if (state.currentActivity.currentGuess.length <
        int.parse(state.currentActivity.activitySettings
            .get(ApplicationConfig.parameterCodeWordLength))) {
      state.currentActivity.currentGuess = state.currentActivity.currentGuess + letter;
      refresh();
    }
  }

  void currentGuessRemoveLetter() {
    if (state.currentActivity.currentGuess.isNotEmpty) {
      state.currentActivity.currentGuess = state.currentActivity.currentGuess
          .substring(0, state.currentActivity.currentGuess.length - 1);
      refresh();
    }
  }

  void currentGuessSubmitWord() {
    state.currentActivity.isStarted = true;

    if (state.currentActivity.currentGuess.length ==
        int.parse(state.currentActivity.activitySettings
            .get(ApplicationConfig.parameterCodeWordLength))) {
      if (state.currentActivity.currentGuess == state.currentActivity.word) {
        printlog('Word found!');
        state.currentActivity.foundWord = true;
      }
      addGuess(state.currentActivity.currentGuess);
      refresh();
    }
  }

  void currentGuessSubmitWrongWord() {
    addGuess(state.currentActivity.currentGuess);
    refresh();
  }

  void addFoundLetter(String letter, int i) {
    state.currentActivity.foundLetters = state.currentActivity.foundLetters.substring(0, i) +
        letter +
        state.currentActivity.foundLetters.substring(i + 1);
  }

  void addGuess(String word) {
    state.currentActivity.guesses.add(word);
    state.currentActivity.currentGuess = '';
  }

  void submitWord() {
    if (state.currentActivity.checkWordIsValid(state.currentActivity.currentGuess)) {
      printlog('Ok word allowed: "${state.currentActivity.currentGuess}".');
      currentGuessSubmitWord();
    } else {
      printlog('Unknown word: "${state.currentActivity.currentGuess}".');
      currentGuessSubmitWrongWord();
    }
  }

  List<String> getTips(String candidate) {
    String word = state.currentActivity.word;
    final int wordLength = int.parse(
        state.currentActivity.activitySettings.get(ApplicationConfig.parameterCodeWordLength));

    final List<String> tips = List<String>.filled(wordLength, '', growable: false);

    if ((!state.currentActivity.checkWordIsValid(candidate))) {
      return List<String>.filled(wordLength, 'wrong', growable: false);
    }

    String replaceCharAt(String oldString, int index, String newChar) {
      return oldString.substring(0, index) + newChar + oldString.substring(index + 1);
    }

    // Check correctly placed letters
    for (int i = 0; i < wordLength; i++) {
      if ((tips[i] == '') && (word[i] == candidate[i])) {
        addFoundLetter(word[i], i);
        word = replaceCharAt(word, i, ' ');
        candidate = replaceCharAt(candidate, i, ' ');
        tips[i] = 'good';
      }
    }

    // Check misplaced letters
    for (int i = 0; i < wordLength; i++) {
      for (int j = 0; j < wordLength; j++) {
        if ((candidate[j] != ' ') && (candidate[j] == word[i])) {
          word = replaceCharAt(word, i, ' ');
          candidate = replaceCharAt(candidate, j, ' ');
          tips[j] = 'misplaced';
        }
      }
    }

    return tips;
  }

  @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.toJson(),
    };
  }
}