// 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.

/// Since this file includes Sky/Mojo, it will need to be mocked out for unit
/// tests.
/// Unfortunately, imports can't be replaced, so the best thing to do is to swap
/// out the whole file.
///
/// The goal of the SettingsManager is to handle viewing and editing of the
/// Croupier Settings.
/// loadSettings: Get the settings of the current player or specified userID.
/// saveSettings: For the current player and their userID, save settings.
/// In the background, these values will be synced.
/// When setting up a syncgroup, the userIDs are very important.

import '../../logic/game/game.dart' as logic_game;
import '../../logic/croupier_settings.dart' show CroupierSettings;
import 'croupier_client.dart' show CroupierClient;
import 'discovery_client.dart' show DiscoveryClient;
import 'util.dart' as util;

import 'dart:async';
import 'dart:convert' show UTF8, JSON;

import 'package:v23discovery/discovery.dart' as discovery;
import 'package:syncbase/syncbase_client.dart' as sc;

class SettingsManager {
  final util.updateCallbackT updateSettingsCallback;
  final util.updateCallbackT updateGamesCallback;
  final util.updateCallbackT updatePlayerFoundCallback;
  final CroupierClient _cc;
  sc.SyncbaseTable tb;

  static const String _discoverySettingsKey = "settings";
  static const String _personalKey = "personal";
  static const String _settingsWatchSyncPrefix = "users";

  SettingsManager(this.updateSettingsCallback, this.updateGamesCallback,
      this.updatePlayerFoundCallback)
      : _cc = new CroupierClient();

  String _settingsDataKey(int userID) {
    return "${_settingsWatchSyncPrefix}/${userID}/settings";
  }

  String _settingsDataKeyUserID(String dataKey) {
    List<String> parts = dataKey.split("/");
    return parts[parts.length - 2];
  }

  Future _prepareSettingsTable() async {
    if (tb != null) {
      return; // Then we're already prepared.
    }

    sc.SyncbaseNoSqlDatabase db = await _cc.createDatabase();
    tb = await _cc.createTable(db, util.tableNameSettings);

    // Start to watch the stream for the shared settings table.
    Stream<sc.WatchChange> watchStream = db.watch(util.tableNameSettings,
        _settingsWatchSyncPrefix, await db.getResumeMarker());
    _startWatchSettings(watchStream); // Don't wait for this future.
    _loadSettings(tb); // Don't wait for this future.
  }

  // Guaranteed to be called when the program starts.
  // If no Croupier Settings exist, then random ones are created.
  Future<String> load() async {
    util.log('SettingsManager.load');
    await _prepareSettingsTable();

    int userID = await _getUserID();
    if (userID == null) {
      CroupierSettings settings = new CroupierSettings.random();
      String jsonStr = settings.toJSONString();
      await this.save(settings.userID, jsonStr);
      return jsonStr;
    } else {
      return await _tryReadData(tb, this._settingsDataKey(userID));
    }
  }

  Future<String> _tryReadData(sc.SyncbaseTable st, String rowkey) async {
    var row = st.row(rowkey);
    if (!(await row.exists())) {
      print("${rowkey} did not exist");
      return null;
    }
    return UTF8.decode(await row.get());
  }

  // Note: only the current user is allowed to save settings.
  // This means we can also save their user id.
  // All other settings will be synced instead.
  Future save(int userID, String jsonString) async {
    util.log('SettingsManager.save');
    await _prepareSettingsTable();

    await tb.row(_personalKey).put(UTF8.encode("${userID}"));
    await tb.row(this._settingsDataKey(userID)).put(UTF8.encode(jsonString));
  }

  // This watch method ensures that any changes are propagated to the caller.
  // In the case of the settings manager, we're checking for any changes to
  // any person's Croupier Settings.
  Future _startWatchSettings(Stream<sc.WatchChange> watchStream) async {
    util.log('Settings watching for changes...');
    // This stream never really ends, so I guess we'll watch forever.
    await for (sc.WatchChange wc in watchStream) {
      assert(wc.tableName == util.tableNameSettings);
      util.log('Watch Key: ${wc.rowKey}');
      util.log('Watch Value ${UTF8.decode(wc.valueBytes)}');
      String key = wc.rowKey;
      String value;
      switch (wc.changeType) {
        case sc.WatchChangeTypes.put:
          value = UTF8.decode(wc.valueBytes);
          break;
        case sc.WatchChangeTypes.delete:
          value = null;
          break;
        default:
          assert(false);
      }

      if (this.updateSettingsCallback != null) {
        this.updateSettingsCallback(_settingsDataKeyUserID(key), value);
      }
    }
  }

  // Best called after load(), to ensure that there are settings in the table.
  Future createSettingsSyncgroup() async {
    int id = await _getUserID();

    _cc.createSyncgroup(
        _cc.makeSyncgroupName(await _syncSuffix()), util.tableNameSettings,
        prefix: this._settingsDataKey(id));
  }

  // This watch method ensures that any changes are propagated to the caller.
  // In this case, we're forwarding any player changes to the Croupier logic.
  Future _startWatchPlayers(Stream<sc.WatchChange> watchStream) async {
    util.log('Players watching for changes...');
    // This stream never really ends, so I guess we'll watch forever.
    await for (sc.WatchChange wc in watchStream) {
      assert(wc.tableName == util.tableNameGames);
      util.log('Watch Key: ${wc.rowKey}');
      util.log('Watch Value ${UTF8.decode(wc.valueBytes)}');
      String key = wc.rowKey;
      String value;
      switch (wc.changeType) {
        case sc.WatchChangeTypes.put:
          value = UTF8.decode(wc.valueBytes);
          break;
        case sc.WatchChangeTypes.delete:
          value = null;
          break;
        default:
          assert(false);
      }

      if (this.updatePlayerFoundCallback != null) {
        String playerID = _getPartFromBack(key, "/", 1);
        this.updatePlayerFoundCallback(playerID, value);

        // Also, you should be sure to join this person's syncgroup.
        _cc.joinSyncgroup(
            _cc.makeSyncgroupName(await _syncSuffix(int.parse(playerID))));
      }
    }
  }

  Future<logic_game.GameStartData> createGameSyncgroup(
      String type, int gameID) async {
    print("Creating game syncgroup for ${type} and ${gameID}");
    sc.SyncbaseNoSqlDatabase db = await _cc.createDatabase();
    sc.SyncbaseTable gameTable = await _cc.createTable(db, util.tableNameGames);

    // Watch for the players in the game.
    Stream<sc.WatchChange> watchStream = db.watch(util.tableNameGames,
        util.syncgamePrefix(gameID) + "/players", await db.getResumeMarker());
    _startWatchPlayers(watchStream); // Don't wait for this future.

    print("Now writing to some rows of ${gameID}");
    // Start up the table and write yourself as player 0.
    await gameTable.row("${gameID}/type").put(UTF8.encode("${type}"));

    int id = await _getUserID();
    await gameTable.row("${gameID}/owner").put(UTF8.encode("${id}"));
    await gameTable
        .row("${gameID}/players/${id}/player_number")
        .put(UTF8.encode("0"));

    logic_game.GameStartData gsd =
        new logic_game.GameStartData(type, 0, gameID, id);

    await _cc.createSyncgroup(
        _cc.makeSyncgroupName(util.syncgameSuffix(gsd.toJSONString())),
        util.tableNameGames,
        prefix: util.syncgamePrefix(gameID));

    return gsd;
  }

  Future joinGameSyncgroup(String sgName, int gameID) async {
    print("Now joining game syncgroup at ${sgName} and ${gameID}");
    sc.SyncbaseSyncgroup sg = await _cc.joinSyncgroup(sgName);

    sc.SyncbaseNoSqlDatabase db = await _cc.createDatabase();
    sc.SyncbaseTable gameTable = await _cc.createTable(db, util.tableNameGames);

    // Watch for the players in the game.
    Stream<sc.WatchChange> watchStream = db.watch(util.tableNameGames,
        util.syncgamePrefix(gameID) + "/players", await db.getResumeMarker());
    _startWatchPlayers(watchStream); // Don't wait for this future.

    // Also write yourself to the table as player |NUM_PLAYERS - 1|
    Map<String, sc.SyncgroupMemberInfo> fellowPlayers = await sg.getMembers();
    print("I have found! ${fellowPlayers} ${fellowPlayers.length}");

    int id = await _getUserID();
    int playerNumber = fellowPlayers.length - 1;
    gameTable
        .row("${gameID}/players/${id}/player_number")
        .put(UTF8.encode("${playerNumber}"));
  }

  // When starting the settings manager, there may be settings already in the
  // store. Make sure to load those.
  Future _loadSettings(sc.SyncbaseTable tb) async {
    tb
        .scan(new sc.RowRange.prefix(_settingsWatchSyncPrefix))
        .forEach((sc.KeyValue kv) {
      if (kv.key.endsWith("/settings")) {
        // Then we can process the value as if it were settings data.
        this.updateSettingsCallback(
            _settingsDataKeyUserID(kv.key), UTF8.decode(kv.value));
      }
    });
  }

  // TODO(alexfandrianto): It is possible that the more efficient way of
  // scanning is to do it for only short bursts. In that case, we should call
  // stopScanSettings a few seconds after starting it.

  // Someone who is creating a game should scan for players who wish to join.
  Future scanSettings() async {
    SettingsScanHandler ssh =
        new SettingsScanHandler(_cc, this.updateGamesCallback);
    _cc.discoveryClient
        .scan(_discoverySettingsKey, "CroupierSettingsAndGame", ssh);
  }

  void stopScanSettings() {
    _cc.discoveryClient.stopScan(_discoverySettingsKey);
  }

  // Someone who wants to join a game should advertise their presence.
  Future advertiseSettings(logic_game.GameStartData gsd) async {
    String suffix = await _syncSuffix();
    String gameSuffix = util.syncgameSuffix(gsd.toJSONString());
    _cc.discoveryClient.advertise(
        _discoverySettingsKey,
        DiscoveryClient.serviceMaker(
            interfaceName: "CroupierSettingsAndGame",
            addrs: <String>[
              _cc.makeSyncgroupName(suffix),
              _cc.makeSyncgroupName(gameSuffix)
            ]));
  }

  void stopAdvertiseSettings() {
    _cc.discoveryClient.stopAdvertise(_discoverySettingsKey);
  }

  Future<int> _getUserID() async {
    String result = await _tryReadData(tb, _personalKey);
    if (result == null) {
      return null;
    }
    return int.parse(result);
  }

  Future<String> _syncSuffix([int userID]) async {
    int id = userID;
    if (id == null) {
      id = await _getUserID();
    }

    return "${util.sgSuffix}-${id}";
  }
}

String _getPartFromBack(String input, String separator, int indexFromLast) {
  List<String> parts = input.split(separator);
  return parts[parts.length - 1 - indexFromLast];
}

// Implementation of the ScanHandler for Settings information.
// Upon finding a settings advertiser, you want to join the syncgroup that
// they're advertising.
class SettingsScanHandler extends discovery.ScanHandler {
  CroupierClient _cc;
  Map<List<int>, String> settingsAddrs;
  Map<List<int>, String> gameAddrs;
  util.updateCallbackT updateGamesCallback;

  SettingsScanHandler(this._cc, this.updateGamesCallback) {
    settingsAddrs = new Map<List<int>, String>();
    gameAddrs = new Map<List<int>, String>();
  }

  void found(discovery.Service s) {
    util.log(
        "SettingsScanHandler Found ${s.instanceUuid} ${s.instanceName} ${s.addrs}");

    if (s.addrs.length == 2) {
      // Note: Assumes 2 addresses.
      settingsAddrs[s.instanceUuid] = s.addrs[0];
      gameAddrs[s.instanceUuid] = s.addrs[1];

      String json = _getPartFromBack(s.addrs[1], "-", 0);
      updateGamesCallback(s.addrs[1], json);

      _cc.joinSyncgroup(s.addrs[0]);
    } else {
      // An unexpected service was found. Who is advertising it?
      // https://github.com/vanadium/issues/issues/846
      util.log("Unexpected service found: ${s.toString()}");
    }
  }

  void lost(List<int> instanceId) {
    util.log("SettingsScanHandler Lost ${instanceId}");

    // TODO(alexfandrianto): Leave the syncgroup?
    // Looks like leave isn't actually implemented, so we can't do this.
    String addr = gameAddrs[instanceId];
    if (addr != null) {
      List<String> parts = addr.split("-");
      String gameID = parts[parts.length - 1];
      updateGamesCallback(gameID, null);
    }
    settingsAddrs.remove(instanceId);
    gameAddrs.remove(instanceId);
  }
}
