// 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);
    return new List<ChromeTab>.from(
        jsonDecode(respBody).map((m) => new ChromeTab(m)));
  }

  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 T WipEventTransformer<T>(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<T> eventStream<T>(String method, WipEventTransformer<T> transformer) {
    return _eventStreams.putIfAbsent(
      method,
      () => new StreamTransformer.fromHandlers(
            handleData: (WipEvent event, EventSink<T> 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;
}
