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

/**
 * A library to connect to a Webkit Inspection Protocol server (like Chrome).
 */
library wip;

import 'dart:async';
import 'dart:convert';
import 'dart:io' show HttpClient, HttpClientResponse, WebSocket;

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

import 'src/console.dart';
import 'src/debugger.dart';
import 'src/dom.dart';
import 'src/log.dart';
import 'src/page.dart';
import 'src/runtime.dart';

export 'src/console.dart';
export 'src/debugger.dart';
export 'src/dom.dart';
export 'src/log.dart';
export 'src/page.dart';
export 'src/runtime.dart';

/**
 * A class to connect to a Chrome instance and reflect on its available tabs.
 *
 * This assumes the browser has been started with the `--remote-debugging-port`
 * flag. The data is read from the `http://{host}:{port}/json` url.
 */
class ChromeConnection {
  final HttpClient _client = new HttpClient();

  final Uri url;

  ChromeConnection(String host, [int port = 9222])
      : url = Uri.parse('http://${host}:${port}/');

  // TODO(DrMarcII): consider changing this to return Stream<ChromeTab>.
  Future<List<ChromeTab>> getTabs() async {
    var response = await getUrl('/json');
    var respBody = await utf8.decodeStream(response);
    List<Map<String, String>> data = jsonDecode(respBody);
    return data.map((m) => new ChromeTab(m)).toList();
  }

  Future<ChromeTab> getTab(bool accept(ChromeTab tab),
      {Duration retryFor}) async {
    var start = new DateTime.now();
    var end = start;
    if (retryFor != null) {
      end = start.add(retryFor);
    }

    while (true) {
      try {
        for (var tab in await getTabs()) {
          if (accept(tab)) {
            return tab;
          }
        }
        if (end.isBefore(new DateTime.now())) {
          return null;
        }
      } catch (e) {
        if (end.isBefore(new DateTime.now())) {
          rethrow;
        }
      }
      await new Future.delayed(new Duration(milliseconds: 25));
    }
  }

  Future<HttpClientResponse> getUrl(String path) async {
    var request = await _client.getUrl(url.resolve(path));
    return await request.close();
  }

  void close() => _client.close(force: true);
}

class ChromeTab {
  final Map _map;

  ChromeTab(this._map);

  String get description => _map['description'];
  String get devtoolsFrontendUrl => _map['devtoolsFrontendUrl'];
  String get faviconUrl => _map['faviconUrl'];

  /// Ex. `E1999E8A-EE27-0450-9900-5BFF4C69CA83`.
  String get id => _map['id'];

  String get title => _map['title'];

  /// Ex. `background_page`, `page`.
  String get type => _map['type'];

  String get url => _map['url'];

  /// Ex. `ws://localhost:1234/devtools/page/4F98236D-4EB0-7C6C-5DD1-AF9B6BE4BC71`.
  String get webSocketDebuggerUrl => _map['webSocketDebuggerUrl'];

  bool get hasIcon => _map.containsKey('faviconUrl');
  bool get isChromeExtension => url.startsWith('chrome-extension://');
  bool get isBackgroundPage => type == 'background_page';

  Future<WipConnection> connect() =>
      WipConnection.connect(webSocketDebuggerUrl);

  String toString() => url;
}

/**
 * A Webkit Inspection Protocol (WIP) connection.
 */
class WipConnection {
  static final _logger = new Logger('WipConnection');

  /**
   * The WebSocket URL.
   */
  final String url;

  final WebSocket _ws;

  int _nextId = 0;

  WipConsole _console; // ignore: deprecated_member_use
  @Deprecated('This domain is deprecated - use Runtime or Log instead')
  WipConsole get console => _console;

  WipDebugger _debugger;
  WipDebugger get debugger => _debugger;

  WipDom _dom;
  WipDom get dom => _dom;

  WipPage _page;
  WipPage get page => _page;

  WipLog _log;
  WipLog get log => _log;

  WipRuntime _runtime;
  WipRuntime get runtime => _runtime;

  final Map _completers = <int, Completer<WipResponse>>{};

  final StreamController _closeController =
      new StreamController<WipConnection>.broadcast();
  final StreamController _notificationController =
      new StreamController<WipEvent>.broadcast();

  static Future<WipConnection> connect(String url) {
    return WebSocket.connect(url).then((socket) {
      return new WipConnection._(url, socket);
    });
  }

  WipConnection._(this.url, this._ws) {
    _console = new WipConsole(this); // ignore: deprecated_member_use
    _debugger = new WipDebugger(this);
    _dom = new WipDom(this);
    _page = new WipPage(this);
    _log = new WipLog(this);
    _runtime = new WipRuntime(this);

    _ws.listen((data) {
      var json = jsonDecode(data);

      if (json.containsKey('id')) {
        _handleResponse(json);
      } else {
        _handleNotification(json);
      }
    }, onDone: _handleClose);
  }

  Stream<WipConnection> get onClose => _closeController.stream;
  Stream<WipEvent> get onNotification => _notificationController.stream;

  Future close() => _ws.close();

  String toString() => url;

  Future<WipResponse> sendCommand(String method,
      [Map<String, dynamic> params]) {
    _logger.finest('Sending command: $method($params)');
    var completer = new Completer<WipResponse>();
    var json = {'id': _nextId++, 'method': method};
    if (params != null) {
      json['params'] = params;
    }
    _completers[json['id']] = completer;
    _ws.add(jsonEncode(json));
    return completer.future;
  }

  void _handleNotification(Map<String, dynamic> json) {
    _logger.finest('Received notification: $json');
    _notificationController.add(new WipEvent(json));
  }

  void _handleResponse(Map<String, dynamic> event) {
    var completer = _completers.remove(event['id']);

    if (event.containsKey('error')) {
      _logger.info('Received error: $event');
      completer.completeError(new WipError(event));
    } else {
      _logger.finest('Received response: $event');
      completer.complete(new WipResponse(event));
    }
  }

  void _handleClose() {
    _closeController.add(this);
    _closeController.close();
    _notificationController.close();
  }
}

class WipEvent {
  final String method;
  final Map<String, dynamic> params;

  WipEvent(Map<String, dynamic> map)
      : method = map['method'],
        params = map['params'];

  String toString() => 'WipEvent: $method($params)';
}

class WipError {
  final int id;
  final dynamic error;

  WipError(Map<String, dynamic> json)
      : id = json['id'],
        error = json['error'];

  String toString() => 'WipError $id: $error';
}

class WipResponse {
  final int id;
  final Map<String, dynamic> result;

  WipResponse(Map<String, dynamic> json)
      : id = json['id'],
        result = json['result'];

  String toString() => 'WipResponse $id: $result';
}

typedef WipEvent WipEventTransformer(WipEvent event);

/// @optional
const String optional = 'optional';

abstract class WipDomain {
  Map<String, Stream> _eventStreams = {};

  final WipConnection connection;
  var _onClosed;
  Stream<WipDomain> get onClosed => _onClosed;

  WipDomain(WipConnection connection) : this.connection = connection {
    this._onClosed =
        new StreamTransformer.fromHandlers(handleData: (event, EventSink sink) {
      sink.add(this);
    }).bind(connection.onClose);
  }

  Stream<WipEvent> eventStream(String method, WipEventTransformer transformer) {
    return _eventStreams.putIfAbsent(
      method,
      () => new StreamTransformer.fromHandlers(
            handleData: (WipEvent event, EventSink<WipEvent> sink) {
              if (event.method == method) {
                sink.add(transformer(event));
              }
            },
          ).bind(connection.onNotification),
    );
  }

  Future<WipResponse> sendCommand(
    String method, {
    Map<String, dynamic> params,
  }) {
    return connection.sendCommand(method, params);
  }
}

class WrappedWipEvent implements WipEvent {
  final WipEvent _wrapped;

  WrappedWipEvent(this._wrapped);

  @override
  String get method => _wrapped.method;

  @override
  Map<String, dynamic> get params => _wrapped.params;
}
