// 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 '../../settings/client.dart' as settings_client;
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.keyValueCallback updateSettingsCallback;
  final util.keyValueCallback updateGamesCallback;
  final util.keyValueCallback updatePlayerFoundCallback;
  final CroupierClient _cc;
  sc.SyncbaseTable tb;

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

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

  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.SyncbaseDatabase 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, UTF8.encode("now"));
    _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(
        await _mySettingsSyncgroupName(), util.tableNameSettings,
        prefix: this._settingsDataKey(id));
  }

  Future<String> _mySettingsSyncgroupName() async {
    return _cc.makeSyncgroupName(await _syncSettingsSuffix());
  }

  // 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);
        String type = _getPartFromBack(key, "/", 0);
        switch (type) {
          case "player_number":
            // Update the player number for this player.
            this.updatePlayerFoundCallback(playerID, value);
            break;
          case "settings_sg":
            // Join this player's settings syncgroup.
            _cc.joinSyncgroup(value);
            break;
          default:
            print("Unexpected key: ${key} with value ${value}");
            assert(false);
        }
      }
    }
  }

  Future<logic_game.GameStartData> createGameSyncgroup(
      String type, int gameID) async {
    print("Creating game syncgroup for ${type} and ${gameID}");
    sc.SyncbaseDatabase 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", UTF8.encode("now"));
    _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"));
    await gameTable
        .row("${gameID}/players/{$id}/settings_sg")
        .put(UTF8.encode(await _mySettingsSyncgroupName()));

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

    await _cc.createSyncgroup(
        _cc.makeSyncgroupName(util.syncgameSuffix("${gsd.gameID}")),
        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.SyncbaseDatabase 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", UTF8.encode("now"));
    _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;
    await gameTable
        .row("${gameID}/players/${id}/player_number")
        .put(UTF8.encode("${playerNumber}"));
    await gameTable
        .row("${gameID}/players/{$id}/settings_sg")
        .put(UTF8.encode(await _mySettingsSyncgroupName()));
  }

  // 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);
    return _cc.discoveryClient.scan(_discoverySettingsKey,
        'v.InterfaceName="${util.discoveryInterfaceName}"', ssh);
  }

  Future stopScanSettings() {
    return _cc.discoveryClient.stopScan(_discoverySettingsKey);
  }

  // Someone who wants to join a game should advertise their presence.
  Future advertiseSettings(logic_game.GameStartData gsd) async {
    String settingsSuffix = await _syncSettingsSuffix();
    String gameSuffix = util.syncgameSuffix("${gsd.gameID}");
    return _cc.discoveryClient.advertise(
        _discoverySettingsKey,
        DiscoveryClient.serviceMaker(
            interfaceName: util.discoveryInterfaceName,
            attrs: <String, String>{
              util.syncgameSettingsAttr: _cc.makeSyncgroupName(settingsSuffix),
              util.syncgameGameStartDataAttr: gsd.toJSONString()
            },
            addrs: <String>[_cc.makeSyncgroupName(gameSuffix)]));
  }

  Future stopAdvertiseSettings() {
    return _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> _syncSettingsSuffix([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<String, String> settingsAddrs;
  Map<String, String> gameAddrs;
  util.keyValueCallback updateGamesCallback;

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

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

    if (s.addrs.length == 1 && s.attrs != null) {
      // Note: Assumes 1 address and attributes for the game.
      settingsAddrs[s.instanceId] = s.attrs[util.syncgameSettingsAttr];
      gameAddrs[s.instanceId] = s.addrs[0];

      String gameSettingsJSON = s.attrs[util.syncgameGameStartDataAttr];
      updateGamesCallback(gameAddrs[s.instanceId], gameSettingsJSON);

      _cc.joinSyncgroup(settingsAddrs[s.instanceId]);
    } 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(String 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) {
      updateGamesCallback(addr, null);
    }
    settingsAddrs.remove(instanceId);
    gameAddrs.remove(instanceId);
  }
}
