// Copyright 2015 Google. All rights reserved. Use of this source code is
// governed by a BSD-style license that can be found in the LICENSE file.

library crmux.forwarder;

import 'dart:async'
    show
        Completer,
        Future,
        Stream,
        StreamController,
        StreamSink,
        StreamSubscription;
import 'dart:convert' show JSON;

import 'package:logging/logging.dart' show Logger;

import 'dom_model.dart' show flattenAttributesMap;
import 'webkit_inspection_protocol.dart'
    show WipConnection, WipDom, WipError, WipEvent, WipResponse;

/// Forwards a [Stream] to a [WipConnection] and events
/// from a [WipConnection] to a [StreamSink].
class WipForwarder {
  static final _log = new Logger('ChromeForwarder');

  final Stream _in;
  final StreamSink _out;
  final WipConnection _debugger;
  final WipDom domModel;

  final _subscriptions = <StreamSubscription>[];

  final _closedController = new StreamController.broadcast();

  factory WipForwarder(WipConnection debugger, Stream stream,
      {StreamSink sink, WipDom domModel}) {
    if (sink == null) {
      sink = stream as StreamSink;
    }
    return new WipForwarder._(debugger, stream, sink, domModel);
  }

  WipForwarder._(this._debugger, this._in, this._out, this.domModel) {
    _subscriptions.add(_in.listen(_onClientDataHandler,
        onError: _onClientErrorHandler, onDone: _onClientDoneHandler));
    _subscriptions.add(_debugger.onNotification.listen(_onDebuggerDataHandler,
        onError: _onDebuggerErrorHandler, onDone: _onDebuggerDoneHandler));
  }

  Future _onClientDataHandler(String data) async {
    var json = JSON.decode(data);
    var response = {'id': json['id']};
    _log.info('Forwarding to debugger: $data');
    try {
      String method = json['method'];
      Map<String, dynamic> params = json['params'];
      bool processed = false;

      if (domModel != null) {
        switch (method) {
          case 'DOM.getDocument':
            response['result'] = {'root': (await domModel.getDocument())};
            processed = true;
            break;
          case 'DOM.getAttributes':
            var attributes = flattenAttributesMap(
                await domModel.getAttributes(params['nodeId']));
            response['result'] = {'attributes': attributes};
            processed = true;
            break;
        }
      }
      if (!processed) {
        WipResponse resp = await _debugger.sendCommand(method, params);
        if (resp.result != null) {
          response['result'] = resp.result;
        }
      }
    } on WipError catch (e) {
      response['error'] = e.error;
    } catch (e, s) {
      _log.severe(json['id'], e.toString(), s);
      response['error'] = e.toString();
    }
    _log.info('forwarding response: $response');
    _out.add(JSON.encode(response));
  }

  void _onClientErrorHandler(Object error, StackTrace stackTrace) {
    _log.severe('error from forwarded client', error, stackTrace);
  }

  void _onClientDoneHandler() {
    _log.info('forwarded client closed.');
    stop();
  }

  void _onDebuggerDataHandler(WipEvent event) {
    _log.info('forwarding event: $event');
    var json = {'method': event.method};
    if (event.params != null) {
      json['params'] = event.params;
    }
    _out.add(JSON.encode(json));
  }

  void _onDebuggerErrorHandler(Object error, StackTrace stackTrace) {
    _log.severe('error from debugger', error, stackTrace);
  }

  void _onDebuggerDoneHandler() {
    _log.info('debugger closed');
    stop();
  }

  void pause() {
    assert(_subscriptions.isNotEmpty);
    _log.info('Pausing forwarding');
    _subscriptions.forEach((s) => s.pause());
    _subscriptions.clear();
  }

  void resume() {
    assert(_subscriptions.isNotEmpty);
    _log.info('Resuming forwarding');
    _subscriptions.forEach((s) => s.resume());
    _subscriptions.clear();
  }

  Future stop() {
    assert(_subscriptions.isNotEmpty);
    _log.info('Stopping forwarding');
    _subscriptions.forEach((s) => s.cancel());
    _subscriptions.clear();
    _closedController.add(null);
    return Future.wait([_closedController.close(), _out.close()]);
  }

  Stream get onClosed => _closedController.stream;
}
