// 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 'discovery_client.dart' show DiscoveryClient;
import 'util.dart' as util;

import 'dart:async';
import 'dart:io' show Platform;

import 'package:v23discovery/discovery.dart' as discovery;
import 'package:flutter/services.dart' show shell;
import 'package:syncbase/src/naming/util.dart' as naming;
import 'package:syncbase/syncbase_client.dart' as sc;

class CroupierClient {
  final sc.SyncbaseClient _syncbaseClient;
  final DiscoveryClient _discoveryClient;
  static final String syncbaseServerUrl = Platform.environment[
          'SYNCBASE_SERVER_URL'] ??
      'https://mojo.v.io/syncbase_server.mojo';

  static final String discoveryTestKey = "TEST";

  // We want CroupierClient to be a singleton for simplicity purposes.
  // This prevents duplicate table/database creation.
  static final CroupierClient _singleton = new CroupierClient._internal();
  factory CroupierClient() {
    return _singleton;
  }

  CroupierClient._internal()
      : _syncbaseClient =
            new sc.SyncbaseClient(shell.connectToService, syncbaseServerUrl),
        _discoveryClient = new DiscoveryClient() {
    print('Fetching syncbase_server.mojo from $syncbaseServerUrl');

    // TODO(alexfandrianto): Remove this test advertisement once we are more
    // comfortable with Discovery.
    String interfaceName = "HelloWorld!";
    _discoveryClient.scan(discoveryTestKey,
        'v.InterfaceName="${interfaceName}"', new MyScanHandler());
    _discoveryClient.advertise(
        discoveryTestKey,
        DiscoveryClient.serviceMaker(
            interfaceName: interfaceName, addrs: ["dummy address"]));
  }

  DiscoveryClient get discoveryClient => _discoveryClient;

  // TODO(alexfandrianto): Try not to call this twice at the same time.
  // That would lead to very race-y behavior.
  Future<sc.SyncbaseDatabase> createDatabase() async {
    util.log('CroupierClient.createDatabase');
    var app = _syncbaseClient.app(util.appName);
    if (!(await app.exists())) {
      await app.create(util.openPerms);
    }
    util.log('CroupierClient.got app');
    var db = app.noSqlDatabase(util.dbName);
    if (!(await db.exists())) {
      await db.create(util.openPerms);
    }
    util.log('CroupierClient.got db');
    return db;
  }

  Completer _tableLock;

  // TODO(alexfandrianto): Try not to call this twice at the same time.
  // That would lead to very race-y behavior.
  Future<sc.SyncbaseTable> createTable(
      sc.SyncbaseDatabase db, String tableName) async {
    if (_tableLock != null) {
      await _tableLock.future;
    }
    _tableLock = new Completer();
    var table = db.table(tableName);
    if (!(await table.exists())) {
      await table.create(util.openPerms);
    }
    util.log('CroupierClient: ${tableName} is ready');
    _tableLock.complete();
    return table;
  }

  // Creates (or joins) a syncgroup with the associated parameters.
  Future<sc.SyncbaseSyncgroup> createSyncgroup(String sgName, String tableName,
      {String prefix, String description, sc.Perms permissions}) async {
    util.log("CroupierClient: Creating syncgroup ${sgName}");

    // TODO(alexfandrianto): destroy is still unimplemented. Thus, we must do a
    // join or create for this syncgroup.
    try {
      util.log("CroupierClient: But first attempting to join ${sgName}");
      sc.SyncbaseSyncgroup sg = await joinSyncgroup(sgName);
      util.log("CroupierClient: Successfully joined ${sgName}");
      return sg;
    } catch (e) {
      util.log(
          "CroupierClient: ${sgName} doesn't exist, so actually creating it.");
    }

    var myInfo = sc.SyncbaseClient.syncgroupMemberInfo(syncPriority: 3);
    String mtName = util.mtAddr;

    sc.SyncbaseSyncgroup sg = await _getSyncgroup(sgName);
    var sgSpec = sc.SyncbaseClient.syncgroupSpec(
        // Sync the entire table.
        [sc.SyncbaseClient.syncgroupPrefix(tableName, prefix ?? "")],
        description: description ?? 'test syncgroup',
        perms: permissions ?? util.openPerms,
        mountTables: [mtName]);

    util.log('SGSPEC = $sgSpec');

    await sg.create(sgSpec, myInfo);

    return sg;
  }

  // Joins a syncgroup with the given name.
  Future<sc.SyncbaseSyncgroup> joinSyncgroup(String sgName) async {
    util.log("CroupierClient: Joining syncgroup ${sgName}");
    var myInfo = sc.SyncbaseClient.syncgroupMemberInfo(syncPriority: 3);

    sc.SyncbaseSyncgroup sg = await _getSyncgroup(sgName);
    await sg.join(myInfo);
    return sg;
  }

  // Helper to get the SyncbaseSyncgroup object from the string.
  Future<sc.SyncbaseSyncgroup> _getSyncgroup(String sgName) async {
    sc.SyncbaseDatabase db = await createDatabase();
    return db.syncgroup(sgName);
  }

  // Helper that converts a suffix to a syncgroup name.
  String makeSyncgroupName(String suffix) {
    String mtName = util.mtAddr;
    String sgPrefix = naming.join(mtName, util.sgPrefix);
    String sgName = naming.join(sgPrefix, suffix);
    return sgName;
  }
}

// Example implementation of a ScanHandler.
class MyScanHandler extends discovery.ScanHandler {
  void found(discovery.Service s) {
    util.log("MYSCANHANDLER Found ${s.instanceId} ${s.instanceName}");
  }

  void lost(String instanceId) {
    util.log("MYSCANHANDLER Lost ${instanceId}");
  }
}
