// 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;
  serviceAttrs['presentationid'] = presentation.key;
  v23discovery.Service serviceInfo = new v23discovery.Service()
    ..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);

  v23discovery.AdvertiserAdvertiseResponseParams result =
      await advertiseResponseFuture;
  if (result.err != null) {
    throw result.err;
  }

  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);

  v23discovery.ScannerScanResponseParams result = await scannerResponseFuture;
  if (result.err != null) {
    throw result.err;
  }
  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 {
  Map<String, String> instanceIdToPresentationIdMap = new Map();
  found(v23discovery.Service s) async {
    String key = s.attrs['presentationid'];
    instanceIdToPresentationIdMap[s.instanceId] = key;
    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 us; ignoring.');
      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 instanceId) {
    String presentationId = instanceIdToPresentationIdMap[instanceId];
    if (presentationId == null) {
      return;
    }
    log.info('Lost presentation $presentationId.');
    _onLostEmitter.add(presentationId);
  }
}

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