// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

import 'dart:async';

import '../settings/client.dart' show AppSettings;
import '../src/syncbase/settings_manager.dart' show SettingsManager;
import '../src/syncbase/util.dart' as sync_util;
import 'create_game.dart' as cg;
import 'croupier_settings.dart' show CroupierSettings;
import 'game/game.dart'
    show Game, GameType, GameStartData, stringToGameType, gameTypeToString;

enum CroupierState {
  Welcome,
  ChooseGame,
  JoinGame,
  ArrangePlayers,
  PlayGame,
  ResumeGame
}

typedef void NoArgCb();

class Croupier {
  AppSettings appSettings;
  CroupierState state;
  SettingsManager settings_manager;
  CroupierSettings settings; // null, but loaded asynchronously.
  Map<int,
      CroupierSettings> settings_everyone; // empty, but loaded asynchronously
  Map<String, GameStartData> games_found; // empty, but loads asynchronously
  Map<int, int> players_found; // empty, but loads asynchronously
  Game game; // null until chosen
  int mostRecentGameID; // null until a game was started.
  NoArgCb informUICb;

  // Futures to use in order to cancel scans and advertisements.
  Future _scanFuture;
  Future _advertiseFuture;

  bool debugMode = false; // whether to show debug buttons or not

  Croupier(this.appSettings) {
    state = CroupierState.Welcome;
    settings_everyone = new Map<int, CroupierSettings>();
    games_found = new Map<String, GameStartData>();
    players_found = new Map<int, int>();
    settings_manager = new SettingsManager(
        appSettings,
        _updateSettingsEveryoneCb,
        _updateGamesFoundCb,
        _updatePlayerFoundCb,
        _updateGameStatusCb);

    settings_manager.load().then((String csString) {
      settings = new CroupierSettings.fromJSONString(csString);
      if (this.informUICb != null) {
        this.informUICb();
      }
      settings_manager.createSettingsSyncgroup(); // don't wait for this future.
    });
  }

  // Updates the settings_everyone map as people join the main Croupier syncgroup
  // and change their settings.
  void _updateSettingsEveryoneCb(String key, String json) {
    settings_everyone[int.parse(key)] =
        new CroupierSettings.fromJSONString(json);
    if (this.informUICb != null) {
      this.informUICb();
    }
  }

  void _updateGamesFoundCb(String gameAddr, String jsonData) {
    if (jsonData == null) {
      games_found.remove(gameAddr);
    } else {
      GameStartData gsd = new GameStartData.fromJSONString(jsonData);
      games_found[gameAddr] = gsd;
    }
    if (this.informUICb != null) {
      this.informUICb();
    }
  }

  int userIDFromPlayerNumber(int playerNumber) {
    return players_found.keys.firstWhere(
        (int user) => players_found[user] == playerNumber,
        orElse: () => null);
  }

  void _setCurrentGame(Game g) {
    game = g;
    mostRecentGameID = game.gameID;
  }

  Game _createNewGame(GameType gt) {
    return cg.createGame(gt, this.debugMode, isCreator: true);
  }

  Game _createExistingGame(GameStartData gsd) {
    return cg.createGame(stringToGameType(gsd.type), this.debugMode,
        gameID: gsd.gameID, playerNumber: gsd.playerNumber);
  }

  void _quitGame() {
    if (game != null) {
      game.quit();
      game = null;
    }
  }

  CroupierSettings settingsFromPlayerNumber(int playerNumber) {
    int userID = userIDFromPlayerNumber(playerNumber);
    if (userID != null) {
      return settings_everyone[userID];
    }
    return null;
  }

  void _updatePlayerFoundCb(String playerKey, String playerNum) {
    String gameIDStr = sync_util.gameIDFromGameKey(playerKey);
    if (game == null || game.gameID != int.parse(gameIDStr)) {
      return; // ignore
    }
    String playerID = sync_util.playerIDFromPlayerKey(playerKey);
    int id = int.parse(playerID);
    if (playerNum == null) {
      if (!players_found.containsKey(id)) {
        // The player exists but has not sat down yet.
        players_found[id] = null;
      }
    } else {
      int playerNumber = int.parse(playerNum);
      players_found[id] = playerNumber;

      // If the player number changed was ours, then set it on our game.
      if (id == settings.userID) {
        game.playerNumber = playerNumber;
      }
    }
    if (this.informUICb != null) {
      this.informUICb();
    }
  }

  void _updateGameStatusCb(String statusKey, String newStatus) {
    String gameIDStr = sync_util.gameIDFromGameKey(statusKey);
    if (game == null || game.gameID != int.parse(gameIDStr)) {
      return; // ignore
    }
    switch (newStatus) {
      case "RUNNING":
        if (state == CroupierState.ArrangePlayers) {
          game.startGameSignal();
          setState(CroupierState.PlayGame, null);
        }
        break;
      default:
        print("Ignoring new status: ${newStatus}");
    }
    if (this.informUICb != null) {
      this.informUICb();
    }
  }

  // Sets the next part of croupier state.
  // Depending on the originating state, data can contain extra information that we need.
  void setState(CroupierState nextState, var data) {
    switch (state) {
      case CroupierState.Welcome:
        // data should be empty unless nextState is ResumeGame.
        if (nextState != CroupierState.ResumeGame) {
          assert(data == null);
        }
        break;
      case CroupierState.ChooseGame:
        if (data == null) {
          // Back button pressed.
          break;
        }
        assert(nextState == CroupierState.ArrangePlayers);

        // data should be the game id here.
        GameType gt = data as GameType;
        _setCurrentGame(_createNewGame(gt));

        _advertiseFuture = settings_manager
            .createGameSyncgroup(gameTypeToString(gt), game.gameID)
            .then((GameStartData gsd) {
          if (!game.gameArrangeData.needsArrangement) {
            settings_manager.setPlayerNumber(gsd.gameID, 0);
          }
          // Only the game chooser should be advertising the game.
          return settings_manager.advertiseSettings(gsd);
        }); // don't wait for this future.

        break;
      case CroupierState.JoinGame:
        // Note that if we were in join game, we must have been scanning.
        _scanFuture.then((_) {
          settings_manager.stopScanSettings();
          games_found.clear();
          _scanFuture = null;
        });

        if (data == null) {
          // Back button pressed.
          break;
        }

        // data would probably be the game id again.
        GameStartData gsd = data as GameStartData;
        gsd.playerNumber = null; // At first, there is no player number.
        _setCurrentGame(_createExistingGame(gsd));
        String sgName;
        games_found.forEach((String name, GameStartData g) {
          if (g == gsd) {
            sgName = name;
          }
        });
        assert(sgName != null);

        players_found[gsd.ownerID] = null;
        settings_manager.joinGameSyncgroup(sgName, gsd.gameID).then((_) {
          if (!game.gameArrangeData.needsArrangement) {
            settings_manager.setPlayerNumber(gsd.gameID, 0);
          }
        });

        break;
      case CroupierState.ArrangePlayers:
        // Note that if we were arranging players, we might have been advertising.
        if (_advertiseFuture != null) {
          _advertiseFuture.then((_) {
            settings_manager.stopAdvertiseSettings();
            _advertiseFuture = null;
          });
        }

        // The signal to start or quit is not anything special.
        // data should be empty.
        assert(data == null);
        break;
      case CroupierState.PlayGame:
        break;
      case CroupierState.ResumeGame:
        // Data might be GameStartData. If so, then we must advertise it.
        GameStartData gsd = data;
        if (gsd != null) {
          _advertiseFuture = settings_manager.advertiseSettings(gsd);
        }
        break;
      default:
        assert(false);
    }

    // A simplified way of clearing out the games and players found.
    // They will need to be re-discovered in the future.
    switch (nextState) {
      case CroupierState.Welcome:
        games_found.clear();
        players_found.clear();
        _quitGame();
        break;
      case CroupierState.JoinGame:
        // Start scanning for games since that's what's next for you.
        _scanFuture =
            settings_manager.scanSettings(); // don't wait for this future.
        break;
      case CroupierState.ResumeGame:
        // We need to create the game again.
        int gameIDData = data;
        _resumeGameAsynchronously(gameIDData);
        break;
      default:
        break;
    }

    state = nextState;
  }

  // Resumes the game from the given gameID.
  Future _resumeGameAsynchronously(int gameIDData) async {
    GameStartData gsd = await settings_manager.getGameStartData(gameIDData);
    bool wasOwner = (gsd.ownerID == settings?.userID);
    print(
        "The game was ${gsd.toJSONString()}, and was I the owner? ${wasOwner}");
    _setCurrentGame(_createExistingGame(gsd));

    String sgName = await settings_manager.getGameSyncgroup(gameIDData);
    print("The sg name was ${sgName}");
    await settings_manager.joinGameSyncgroup(sgName, gameIDData);

    // Since initial scan processing is done, we can now set isCreator
    game.isCreator = wasOwner;
    String gameStatus = await settings_manager.getGameStatus(gameIDData);

    print("The game's status was ${gameStatus}");
    // Depending on the game state, we should go to a different screen.
    switch (gameStatus) {
      case "RUNNING":
        // The game is running, so let's play it!
        setState(CroupierState.PlayGame, null);
        break;
      default:
        // We are still arranging players, so we need to advertise our game
        // start data.
        setState(CroupierState.ArrangePlayers, gsd);
        break;
    }

    // And we can ask the UI to redraw
    if (this.informUICb != null) {
      this.informUICb();
    }
  }
}
