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

part of syncbase_client;

class SyncbaseTable extends NamedResource {
  SyncbaseTable._internal(_proxy, _parentFullName, relativeName)
      : super._internal(_proxy, _parentFullName, relativeName,
          naming.join(_parentFullName, escape(relativeName)));

  // row returns a row with the given key.
  SyncbaseRow row(String key) {
    return new SyncbaseRow._internal(_proxy, fullName, key);
  }

  Future create(mojom.Perms perms) async {
    var v = await _proxy.ptr.tableCreate(fullName, perms);
    if (isError(v.err)) throw v.err;
  }

  Future destroy() async {
    var v = await _proxy.ptr.tableDestroy(fullName);
    if (isError(v.err)) throw v.err;
  }

  Future<bool> exists() async {
    var v = await _proxy.ptr.tableExists(fullName);
    if (isError(v.err)) throw v.err;
    return v.exists;
  }

  Future<mojom.Perms> getPermissions() async {
    var v = await _proxy.ptr.tableGetPermissions(fullName);
    if (isError(v.err)) throw v.err;
    return v.perms;
  }

  Future setPermissions(mojom.Perms perms) async {
    var v = await _proxy.ptr.tableSetPermissions(fullName, perms);
    if (isError(v.err)) throw v.err;
  }

  Future<List<int>> get(String key) async {
    return this.row(key).get();
  }

  Future put(String key, List<int> value) async {
    return this.row(key).put(value);
  }

  Future delete(String key) async {
    return this.row(key).delete();
  }

  Future deleteRange(RowRange range) async {
    var v =
        await _proxy.ptr.tableDeleteRange(fullName, range.start, range.limit);
    if (isError(v.err)) throw v.err;
  }

  Stream<mojom.KeyValue> scan(RowRange range) {
    StreamController<mojom.KeyValue> sc = new StreamController();

    mojom.ScanStreamStub stub = new mojom.ScanStreamStub.unbound();
    stub.impl = new ScanStreamImpl._fromStreamController(sc);

    // Call tableScan asynchronously.
    _proxy.ptr.tableScan(fullName, range.start, range.limit, stub).then((v) {
      // TODO(nlacasse): Is throwing the correct behavior here?  Consider
      // returning a tuple (Stream<mojom.KeyValue>, Future) and resolve the
      // Future at the end of the RPC (with an error if applicable).  Then
      // errors will be handled the same in this method as in all the other
      // methods that return Futures.  (Even though the other methods seem to
      // "throw", they are actually resolving a Future since the function is
      // declared with "async".)
      if (isError(v.err)) throw v.err;
    });

    return sc.stream;
  }

  Future<List<mojom.PrefixPerms>> getPrefixPermissions(String key) async {
    var v = await _proxy.ptr.tableGetPrefixPermissions(fullName, key);
    if (isError(v.err)) throw v.err;
    return v.permsArr;
  }

  Future setPrefixPermissions(String prefix, mojom.Perms perms) async {
    var v = await _proxy.ptr.tableSetPrefixPermissions(fullName, prefix, perms);
    if (isError(v.err)) throw v.err;
  }

  Future deletePrefixPermissions(String prefix) async {
    var v = await _proxy.ptr.tableDeletePrefixPermissions(fullName, prefix);
    if (isError(v.err)) throw v.err;
  }
}

class ScanStreamImpl implements mojom.ScanStream {
  final StreamController<mojom.KeyValue> sc;
  ScanStreamImpl._fromStreamController(this.sc);

  Future<mojom.ScanStreamOnChangeResponseParams> onKeyValue(
      mojom.KeyValue keyValue, Function resultFactory) {
    sc.add(keyValue);

    // TODO(aghassemi): Honor the pause state.
    // If stream is paused, return a future that will be completed when stream
    // is resumed. Otherwise we are breaking Dart stream's flow control.

    // Send an ack back to server.
    return new Future.value(resultFactory(true));
  }

  // Called by the mojom proxy when the Go function call returns.
  onReturn(mojom.Error err) {
    if (isError(err)) {
      sc.addError(err);
    }
    sc.close();
  }
}
