import 'dart:async';
import 'dart:math';

import 'package:mnemo_cards_common/mnemo_cards_common.dart';
import 'package:rxdart/rxdart.dart';

import 'question_states/input_buttons_test_state.dart';
import 'question_states/simple_test_state.dart';
import 'question_states/test_question_state.dart';

class TestHolder {
  final StreamController<_TestState?> _streamController =
      StreamController.broadcast();
  _TestState __state;

  TestHolder() : __state = _TestState({}, null);

  void skip(int id) {
    final state = testQuestionState(id);
    print('Skipping $id ${state} ${state?.testType}');
    switch (state?.testType) {
      case TestQuestionType.simple:
        state as SimpleTestState;
        print('Skipped $id ${state.word}');
        setQuestionState(id, state.copyWith(isSkipped: true));
        break;
      case TestQuestionType.input_buttons:
        state as InputButtonsTestState;
        print('Skipped $id ${state.word}');
        setQuestionState(id, state.copyWith(isSkipped: true));
        break;
      case TestQuestionType.matrix:
        // TODO: Handle this case.
        break;
      case TestQuestionType.match:
        // TODO: Handle this case.
        break;
      case TestQuestionType.undefined:
      // TODO: Handle this case.
      case null:
        // TODO: Handle this case.
        break;
    }
  }

  void setQuestionState(int id, TestQuestionState state) {
    _state = _TestState(
      Map.from(_state.questions..[id] = state),
      _state.sessionToken,
    );
  }

  void clear() {
    _state = _TestState({}, null);
    _streamController.add(_state);
  }

  void setQuestions(
      List<AbstractTestQuestion> questions, String? sessionToken) {
    final stateQuestions = <int, TestQuestionState>{};
    final seed = Random().nextInt(999);
    for (final question in questions) {
      switch (question.questionType) {
        case TestQuestionType.simple:
          stateQuestions[question.id!] = SimpleTestState(
            seed: seed,
            word: question.word,
          );
        case TestQuestionType.input_buttons:
          stateQuestions[question.id!] = InputButtonsTestState(
            seed: seed,
            word: question.word,
          );
        case TestQuestionType.matrix:
        // TODO: Handle this case.
        case TestQuestionType.match:
        // TODO: Handle this case.
        case TestQuestionType.undefined:
        // TODO: Handle this case.
      }
    }
    _state = _TestState(stateQuestions, sessionToken);
  }

  TestQuestionState? testQuestionState(int id) => _state.questions[id];

  _TestState get state => _state;

  _TestState get _state => __state;

  void set _state(_TestState state) {
    __state = state;
    _streamController.add(__state);
  }

  Stream<_TestState?> get asStream =>
      _streamController.stream.startWith(_state);
}

class _TestState {
  final String? sessionToken;
  final Map<int, TestQuestionState> questions;

  _TestState(this.questions, this.sessionToken);
}
