// 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, IOException, WebSocket;

import 'src/console.dart';
import 'src/debugger.dart';
import 'src/dom.dart';
import 'src/log.dart';
import 'src/page.dart';
import 'src/runtime.dart';
import 'src/target.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';
export 'src/target.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 = HttpClient();

  final Uri url;

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

  /// Return all the available tabs.
  ///
  /// This method can potentially throw a [ConnectionException] on some protocol
  /// issues.
  ///
  /// An optional [retryFor] duration can be used to automatically re-try
  /// connections for some period of time. Anecdotally, Chrome can return errors
  /// when trying to list the available tabs very early in its startup sequence.
  Future<List<ChromeTab>> getTabs({
    Duration? retryFor,
  }) async {
    final start = DateTime.now();
    DateTime? end = retryFor == null ? null : start.add(retryFor);

    var response = await getUrl('/json');
    var responseBody = await utf8.decodeStream(response.cast<List<int>>());

    late List decoded;
    while (true) {
      try {
        decoded = jsonDecode(responseBody);
        return List<ChromeTab>.from(decoded.map((m) => ChromeTab(m as Map)));
      } on FormatException catch (formatException) {
        if (end != null && end.isBefore(DateTime.now())) {
          // Delay for retryFor / 4 milliseconds.
          await Future.delayed(
            Duration(milliseconds: retryFor!.inMilliseconds ~/ 4),
          );
        } else {
          throw ConnectionException(
            formatException: formatException,
            responseStatus: '${response.statusCode} ${response.reasonPhrase}',
            responseBody: responseBody,
          );
        }
      }
    }
  }

  Future<ChromeTab?> getTab(
    bool Function(ChromeTab tab) accept, {
    Duration? retryFor,
  }) async {
    var start = 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(DateTime.now())) {
          return null;
        }
      } catch (e) {
        if (end.isBefore(DateTime.now())) {
          rethrow;
        }
      }
      await Future.delayed(const 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);
}

/// An exception that can be thrown early in the connection sequence for a
/// [ChromeConnection].
///
/// This exception includes the underlying exception, as well as the http
/// response from the browser that we failed on. The [toString] implementation
/// includes a summary of the response.
class ConnectionException implements IOException {
  final FormatException formatException;
  final String responseStatus;
  final String responseBody;

  ConnectionException({
    required this.formatException,
    required this.responseStatus,
    required this.responseBody,
  });

  @override
  String toString() {
    final buf = StringBuffer('${formatException.message}\n');
    buf.writeln('$responseStatus; body:');
    var lines = responseBody.split('\n');
    if (lines.length > 10) {
      lines = [
        ...lines.take(10),
        '...',
      ];
    }
    buf.writeAll(lines, '\n');
    return buf.toString();
  }
}

class ChromeTab {
  final Map _map;

  ChromeTab(this._map);

  String? get description => _map['description'] as String?;

  String? get devtoolsFrontendUrl => _map['devtoolsFrontendUrl'] as String?;

  String? get faviconUrl => _map['faviconUrl'] as String?;

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

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

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

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

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

  bool get hasIcon => _map.containsKey('faviconUrl');

  bool get isChromeExtension => url.startsWith('chrome-extension://');

  bool get isBackgroundPage => type == 'background_page';

  /// Connect to the debug connection for this tab and return a [WipConnection].
  ///
  /// On errors from this stream, the [onError] handler is called with the error
  /// object and possibly a stack trace. The [onError] callback must be of type
  /// `void Function(Object error)` or `void Function(Object error, StackTrace)`.
  Future<WipConnection> connect({Function? onError}) {
    return WipConnection.connect(webSocketDebuggerUrl, onError: onError);
  }

  @override
  String toString() => url;
}

/// A Webkit Inspection Protocol (WIP) connection.
class WipConnection {
  /// The WebSocket URL.
  final String url;

  final WebSocket _ws;

  int _nextId = 0;

  @Deprecated('This domain is deprecated - use Runtime or Log instead')
  late final WipConsole console = WipConsole(this);

  late final WipDebugger debugger = WipDebugger(this);

  late final WipDom dom = WipDom(this);

  late final WipPage page = WipPage(this);

  late final WipTarget target = WipTarget(this);

  late final WipLog log = WipLog(this);

  late final WipRuntime runtime = WipRuntime(this);

  final StreamController<String> _onSend =
      StreamController.broadcast(sync: true);
  final StreamController<String> _onReceive =
      StreamController.broadcast(sync: true);

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

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

  /// Connect to the given url and return a [WipConnection].
  ///
  /// On errors from this stream, the [onError] handler is called with the error
  /// object and possibly a stack trace. The [onError] callback must be of type
  /// `void Function(Object error)` or `void Function(Object error, StackTrace)`.
  static Future<WipConnection> connect(String url, {Function? onError}) {
    return WebSocket.connect(url).then((socket) {
      return WipConnection._(url, socket, onError: onError);
    });
  }

  WipConnection._(this.url, this._ws, {Function? onError}) {
    void onData(dynamic /*String|List<int>*/ data) {
      _onReceive.add(data);

      var json = jsonDecode(data as String) as Map<String, dynamic>;
      if (json.containsKey('id')) {
        _handleResponse(json);
      } else {
        _handleNotification(json);
      }
    }

    _ws.listen(
      onData,
      onError: onError,
      onDone: _handleClose,
    );
  }

  Stream<WipConnection> get onClose => _closeController.stream;

  Stream<WipEvent> get onNotification => _notificationController.stream;

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

  @override
  String toString() => url;

  Future<WipResponse> sendCommand(
    String method, [
    Map<String, dynamic>? params,
  ]) {
    var completer = Completer<WipResponse>();
    var json = {'id': _nextId++, 'method': method};
    if (params != null) {
      json['params'] = params;
    }
    _completers[json['id'] as int] = completer;
    String message = jsonEncode(json);
    _ws.add(message);
    _onSend.add(message);
    return completer.future;
  }

  void _handleNotification(Map<String, dynamic> json) {
    _notificationController.add(WipEvent(json));
  }

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

    if (event.containsKey('error')) {
      completer.completeError(WipError(event));
    } else {
      completer.complete(WipResponse(event));
    }
  }

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

  /// Listen for all traffic sent on this WipConnection.
  Stream<String> get onSend => _onSend.stream;

  /// Listen for all traffic received by this WipConnection.
  Stream<String> get onReceive => _onReceive.stream;
}

class WipEvent {
  final Map<String, dynamic> json;

  final String method;
  final Map<String, dynamic>? params;

  WipEvent(this.json)
      : method = json['method'] as String,
        params = json['params'] as Map<String, dynamic>?;

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

class WipError implements Exception {
  final Map<String, dynamic> json;

  final int id;
  final Map<String, dynamic>? error;

  WipError(this.json)
      : id = json['id'] as int,
        error = json['error'] as Map<String, dynamic>?;

  int? get code => error == null ? null : error!['code'];

  String? get message => error == null ? null : error!['message'];

  @override
  String toString() => 'WipError $code $message';
}

class WipResponse {
  final Map<String, dynamic> json;

  final int id;
  final Map<String, dynamic>? result;

  WipResponse(this.json)
      : id = json['id'] as int,
        result = json['result'] as Map<String, dynamic>?;

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

typedef WipEventTransformer<T> = T Function(WipEvent event);

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

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

  final WipConnection connection;

  late final Stream<WipDomain> onClosed = StreamTransformer.fromHandlers(
      handleData: (event, EventSink<WipDomain> sink) {
    sink.add(this);
  }).bind(connection.onClose);

  WipDomain(this.connection);

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

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

// ignore: library_private_types_in_public_api
const _Experimental experimental = _Experimental();

class _Experimental {
  const _Experimental();
}
