import 'dart:collection';
import 'dart:io';
import 'dart:math';
import 'package:logging/logging.dart';

import '../entity/pad.dart';
import '../entity/player.dart';
import '../enum/commands.dart';
import '../enum/game_mode.dart';
import '../enum/game_type.dart';

class Sequence {
  Queue<int> sequence;
  List<Pad> pads;
  GameMode gameMode;
  GameType gameType;
  int currentPadLit = -1;
  int lastPadLit = -1;
  int nextPadLit = -1;
  List<String> uuids = [];
  bool byHits = false;
  Pad? currentPad;
  Pad? nextPad;
  String? currentActiveUuid;
  String? color;
  final Logger _log = Logger('Sequence');

  Sequence(List<int> sequence, this.gameMode, this.gameType, this.pads,
      List<Player> players)
      : sequence = Queue.from(sequence) {
    for (final Player player in players) {
      player.resetStats();
    }

    for (final Pad pad in pads) {
      uuids.add(pad.uuid);
    }
  }

  Sequence.random(this.gameType, this.pads, List<Player> players)
      : sequence = Queue.from([]),
        gameMode = GameMode.random {
    for (final Player player in players) {
      player.resetStats();
    }

    for (final Pad pad in pads) {
      uuids.add(pad.uuid);
    }
  }

  void next() {
    switch (gameMode) {
      case GameMode.random:
        if (pads.length > 2) {
          while (true) {
            currentPadLit = Random().nextInt(pads.length + 1);
            if (currentPadLit == lastPadLit) continue;
            _log.fine('Last light up: $lastPadLit');
            _log.fine('Light up: $currentPadLit');
            lastPadLit = currentPadLit;
            break;
          }
        } else {
          currentPadLit = Random().nextInt(pads.length + 1);
          _log.fine('Light up: $currentPadLit');
        }
        _log.fine('Next light up: $nextPadLit');
        break;
      case GameMode.sequence:
        currentPadLit = sequence.removeFirst();
        sequence.add(currentPadLit);
        _log.fine('Light up: $currentPadLit');
        break;
      case GameMode.memory:
        currentPadLit = sequence.removeFirst();
        nextPadLit = sequence.removeFirst();
        sequence.add(currentPadLit);
        sequence.addFirst(nextPadLit);
        _log.fine('Light up: $currentPadLit');
        _log.fine('Next light up: $nextPadLit');
        break;
      default:
        _log.severe('Sequence was not properly set');
        break;
    }

    if (nextPadLit != -1 && currentPadLit != nextPadLit) {
      nextPad = pads.elementAt(nextPadLit);
    } else {
      nextPad = null;
    }

    currentPad = pads.elementAt(currentPadLit);

    for (final Pad pad in pads) {
      if (pad.alive) {
        // pad.active = false
      }
    }

    if (currentPad!.currentStatus != Commands.off) {
      _log.fine('currentActiveUuid from Sequence: $currentActiveUuid');
      _log.fine('currentPad Uuid from Sequence: ${currentPad?.uuid}');

      if (currentActiveUuid == currentPad!.uuid) {
        sleep(const Duration(milliseconds: 300));
        // currentPad.turnOn();
      } else {
        // currentPad.turnOn();
      }
    } else {
      sleep(const Duration(milliseconds: 300));

      _log.fine('currentActiveUuid from Sequence: $currentActiveUuid');
      _log.fine('currentPad Uuid from Sequence: ${currentPad!.uuid}');
      currentActiveUuid = currentPad!.uuid;
      next();
    }
  }

  void reset() {
    lastPadLit = -1;
    currentPadLit = -1;
    nextPadLit = -1;
    currentPad = null;
    nextPad = null;
  }
}
