// 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
  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,
        _gameLogUpdateCb);

    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();
    }
  }

  Future _gameLogUpdateCb(String key, String value, bool duringScan) async {
    if (game != null && game.gamelog.watchUpdateCb != null) {
      await game.gamelog.watchUpdateCb(key, value, duringScan);
    }
  }

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

  void _setCurrentGame(Game g) {
    game = g;
    settings.lastGameID = g.gameID;
    settings_manager.save(settings.userID, settings.toJSONString()); // async
  }

  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) {
      settings_manager.quitGame();
      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);
        } else if (state == CroupierState.ResumeGame) {
          game.startGameSignal();
        }
        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) {
          // 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);

        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();
    }
  }
}
