// 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 Future, Stream, StreamController, StreamSink, StreamSubscription;
import 'dart:convert' show jsonDecode, jsonEncode;

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<String> _in;
  final StreamSink _out;
  final WipConnection _debugger;
  final WipDom domModel;

  /// If false, no Debugger.paused events will be forwarded back to the client.
  /// This gets automatically set to true if a breakpoint is set by the client.
  bool forwardPausedEvents = false;

  final List<StreamSubscription> _subscriptions = <StreamSubscription>[];

  final StreamController<Null> _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 = jsonDecode(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 (method.contains('reakpoint')) {
        forwardPausedEvents = true;
      }

      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(jsonEncode(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) {
    if (event.method == 'Debugger.paused' && !forwardPausedEvents) {
      _log.info('not forwarding event: $event');
      return;
    }
    _log.info('forwarding event: $event');

    var json = <String, dynamic>{'method': event.method};
    if (event.params != null) {
      json['params'] = event.params;
    }
    _out.add(jsonEncode(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;
}
