// 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 'package:flutter/services.dart' show shell;
import 'package:logging/logging.dart';
import 'package:v23discovery/discovery.dart' as v23discovery;

import '../models/all.dart' as model;

final Logger log = new Logger('discovery/client');

const String v23DiscoveryMojoUrl =
    'https://discovery.syncslides.mojo.v.io/discovery.mojo';

// TODO(aghassemi): We should make this the same between Flutter and Java apps when
// they can actually talk to each other.
const String presentationInterfaceName =
    'v.io/release/projects/syncslides/dart/presentation';

StreamController<model.PresentationAdvertisement> _onFoundEmitter =
    new StreamController.broadcast();
StreamController<String> _onLostEmitter = new StreamController.broadcast();

Stream onFound = _onFoundEmitter.stream;
Stream onLost = _onLostEmitter.stream;

// TODO(aghassemi): v23discovery could really use a Dart client library.
// Keep proxy, handle pairs so we can cancel calls later.
ProxyResponseFuturePair<v23discovery.ScannerProxy,
    v23discovery.ScannerScanResponseParams> _scanCall;

Map<
        String,
        ProxyResponseFuturePair<v23discovery.AdvertiserProxy,
            v23discovery.AdvertiserAdvertiseResponseParams>> _advertiseCalls =
    new Map();

Future advertise(model.PresentationAdvertisement presentation) async {
  log.info('Started advertising ${presentation.deck.name}.');
  if (_advertiseCalls.containsKey(presentation.key)) {
    // We are already advertising for this presentation.
    return _advertiseCalls[presentation.key].responseFuture;
  }

  Map<String, String> serviceAttrs = new Map();
  serviceAttrs['deckid'] = presentation.deck.key;
  serviceAttrs['name'] = presentation.deck.name;
  serviceAttrs['thumbnailkey'] = presentation.deck.thumbnail.key;
  v23discovery.Service serviceInfo = new v23discovery.Service()
    ..instanceId = presentation.key
    ..interfaceName = presentationInterfaceName
    ..instanceName = presentation.key
    ..attrs = serviceAttrs
    ..addrs = [presentation.syncgroupName, presentation.thumbnailSyncgroupName];

  v23discovery.AdvertiserProxy advertiser =
      new v23discovery.AdvertiserProxy.unbound();
  shell.connectToService(v23DiscoveryMojoUrl, advertiser);
  Future advertiseResponseFuture = advertiser.ptr.advertise(serviceInfo, null);
  _advertiseCalls[presentation.key] =
      new ProxyResponseFuturePair(advertiser, advertiseResponseFuture);

  await advertiseResponseFuture;
  log.info('Advertised ${presentation.deck.name} under ${presentation.key}.');
}

// Tracks advertisements that are in the middle of being stopped.
Map<String, Future> _stoppingAdvertisingCalls = new Map<String, Future>();
Future stopAdvertising(String presentationId) async {
  if (!_advertiseCalls.containsKey(presentationId)) {
    // Not advertised, nothing to stop.
    return new Future.value();
  }

  if (_stoppingAdvertisingCalls.containsKey(presentationId)) {
    // Already stopping, return the exiting call future.
    return _stoppingAdvertisingCalls[presentationId];
  }

  stop() async {
    v23discovery.AdvertiserAdvertiseResponseParams advertiserResponse =
        await _advertiseCalls[presentationId].responseFuture;

    await _advertiseCalls[presentationId]
        .proxy
        .ptr
        .stop(advertiserResponse.handle);
    await _advertiseCalls[presentationId].proxy.close();
  }

  Future stoppingCall = stop();
  _stoppingAdvertisingCalls[presentationId] = stoppingCall;

  stoppingCall.then((_) {
    _advertiseCalls.remove(presentationId);
    log.info('Stopped advertising ${presentationId}.');
  }).catchError((e) {
    _stoppingAdvertisingCalls.remove(presentationId);
    throw e;
  });
}

Future startScan() async {
  if (_scanCall != null) {
    // We are already scanning.
    return _scanCall.responseFuture;
  }

  var scanner = new v23discovery.ScannerProxy.unbound();
  shell.connectToService(v23DiscoveryMojoUrl, scanner);
  v23discovery.ScanHandlerStub handlerStub =
      new v23discovery.ScanHandlerStub.unbound();
  handlerStub.impl = new ScanHandler();

  var query = 'v.InterfaceName = "$presentationInterfaceName"';
  var scannerResponseFuture = scanner.ptr.scan(query, handlerStub);
  _scanCall = new ProxyResponseFuturePair(scanner, scannerResponseFuture);

  await scannerResponseFuture;
  log.info('Scan started.');
}

// Tracks whether we are already in the middle of stopping scan.
Future _stoppingScanCall;
Future stopScan() async {
  if (_scanCall == null) {
    // No scan call has been made before or scan is already being stopped.
    return new Future.value();
  }

  if (_stoppingScanCall != null) {
    // Already stopping, return the exiting call future.
    return _stoppingScanCall;
  }

  stop() async {
    v23discovery.ScannerScanResponseParams scannerResponse =
        await _scanCall.responseFuture;

    await _scanCall.proxy.ptr.stop(scannerResponse.handle);
    await _scanCall.proxy.close();
  }

  _stoppingScanCall = stop();

  _stoppingScanCall.then((_) {
    _scanCall = null;
    log.info('Scan stopped.');
  }).catchError((e) {
    _stoppingScanCall = null;
    throw e;
  });
}

class ScanHandler extends v23discovery.ScanHandler {
  found(v23discovery.Service s) async {
    String key = s.instanceId;
    log.info('Found presentation ${s.attrs['name']} under $key.');
    // Ignore our own advertised services.
    if (_advertiseCalls.containsKey(key)) {
      log.info(
          'Presentation ${s.attrs['name']} was advertised by this device itself, ignoring it.');
      return;
    }

    model.Deck deck = new model.Deck(s.attrs['deckid'], s.attrs['name'],
        new model.BlobRef(s.attrs['thumbnailkey']));
    var syncgroupName = s.addrs[0];
    var thumbnailSyncgroupName = s.addrs[1];
    model.PresentationAdvertisement presentation =
        new model.PresentationAdvertisement(
            key, deck, syncgroupName, thumbnailSyncgroupName);

    _onFoundEmitter.add(presentation);
  }

  lost(String presentationId) {
    // Ignore our own advertised services.
    log.info('Lost presentation $presentationId.');
    _onLostEmitter.add(presentationId);
  }
}

class ProxyResponseFuturePair<T1, T2> {
  final T1 proxy;
  final Future<T2> responseFuture;
  ProxyResponseFuturePair(this.proxy, this.responseFuture);
}
