// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:async';
import 'dart:js_interop';
import 'dart:typed_data';

import 'package:async/async.dart';
import 'package:stream_channel/stream_channel.dart';
import 'package:web/helpers.dart';

import 'src/channel.dart';
import 'src/exception.dart';
import 'src/web_helpers.dart';

/// A [WebSocketChannel] that communicates using a `dart:html` [WebSocket].
class HtmlWebSocketChannel extends StreamChannelMixin
    implements WebSocketChannel {
  /// The underlying `dart:html` [WebSocket].
  final WebSocket innerWebSocket;

  @override
  String? get protocol => innerWebSocket.protocol;

  @override
  int? get closeCode => _closeCode;
  int? _closeCode;

  @override
  String? get closeReason => _closeReason;
  String? _closeReason;

  /// The number of bytes of data that have been queued but not yet transmitted
  /// to the network.
  int? get bufferedAmount => innerWebSocket.bufferedAmount;

  /// The close code set by the local user.
  ///
  /// To ensure proper ordering, this is stored until we get a done event on
  /// [_controller.local.stream].
  int? _localCloseCode;

  /// The close reason set by the local user.
  ///
  /// To ensure proper ordering, this is stored until we get a done event on
  /// [_controller.local.stream].
  String? _localCloseReason;

  /// Completer for [ready].
  late Completer<void> _readyCompleter;

  @override
  Future<void> get ready => _readyCompleter.future;

  @override
  Stream get stream => _controller.foreign.stream;

  final _controller =
      StreamChannelController<Object?>(sync: true, allowForeignErrors: false);

  @override
  late final WebSocketSink sink = _HtmlWebSocketSink(this);

  /// Creates a new WebSocket connection.
  ///
  /// Connects to [url] using [WebSocket.new] and returns a channel that can be
  /// used to communicate over the resulting socket. The [url] may be either a
  /// [String] or a [Uri]. The [protocols] parameter is the same as for
  /// [WebSocket.new].
  ///
  /// The [binaryType] parameter controls what type is used for binary messages
  /// received by this socket. It defaults to [BinaryType.list], which causes
  /// binary messages to be delivered as [Uint8List]s. If it's
  /// [BinaryType.blob], they're delivered as [Blob]s instead.
  HtmlWebSocketChannel.connect(Object url,
      {Iterable<String>? protocols, BinaryType? binaryType})
      : this(
          WebSocket(
            url.toString(),
            protocols?.map((e) => e.toJS).toList().toJS ?? JSArray(),
          )..binaryType = (binaryType ?? BinaryType.list).value,
        );

  /// Creates a channel wrapping [innerWebSocket].
  HtmlWebSocketChannel(this.innerWebSocket) {
    _readyCompleter = Completer();
    if (innerWebSocket.readyState == WebSocket.OPEN) {
      _readyCompleter.complete();
      _listen();
    } else {
      if (innerWebSocket.readyState == WebSocket.CLOSING ||
          innerWebSocket.readyState == WebSocket.CLOSED) {
        _readyCompleter.completeError(WebSocketChannelException(
            'WebSocket state error: ${innerWebSocket.readyState}'));
      }
      // The socket API guarantees that only a single open event will be
      // emitted.
      innerWebSocket.onOpenX.first.then((_) {
        _readyCompleter.complete();
        _listen();
      });
    }

    // The socket API guarantees that only a single error event will be emitted,
    // and that once it is no open or message events will be emitted.
    innerWebSocket.onErrorX.first.then((_) {
      // Unfortunately, the underlying WebSocket API doesn't expose any
      // specific information about the error itself.
      final error = WebSocketChannelException('WebSocket connection failed.');
      if (!_readyCompleter.isCompleted) {
        _readyCompleter.completeError(error);
      }
      _controller.local.sink.addError(error);
      _controller.local.sink.close();
    });

    innerWebSocket.onMessageX.listen(_innerListen);

    // The socket API guarantees that only a single error event will be emitted,
    // and that once it is no other events will be emitted.
    innerWebSocket.onCloseX.first.then((event) {
      _closeCode = event.code;
      _closeReason = event.reason;
      _controller.local.sink.close();
    });
  }

  void _innerListen(MessageEvent event) {
    // Event data will be ArrayBuffer, Blob, or String.
    final eventData = event.data;
    final Object? data;
    if (eventData.typeofEquals('string')) {
      data = (eventData as JSString).toDart;
    } else if (eventData.typeofEquals('object') &&
        (eventData as JSObject).instanceOfString('ArrayBuffer')) {
      data = (eventData as JSArrayBuffer).toDart.asUint8List();
    } else {
      // Blobs are passed directly.
      data = eventData;
    }
    _controller.local.sink.add(data);
  }

  /// Pipes user events to [innerWebSocket].
  void _listen() {
    _controller.local.stream.listen((obj) => innerWebSocket.send(obj!.jsify()!),
        onDone: () {
      // On Chrome and possibly other browsers, `null` can't be passed as the
      // default here. The actual arity of the function call must be correct or
      // it will fail.
      if ((_localCloseCode, _localCloseReason)
          case (final closeCode?, final closeReason?)) {
        innerWebSocket.close(closeCode, closeReason);
      } else if (_localCloseCode case final closeCode?) {
        innerWebSocket.close(closeCode);
      } else {
        innerWebSocket.close();
      }
    });
  }
}

/// A [WebSocketSink] that tracks the close code and reason passed to [close].
class _HtmlWebSocketSink extends DelegatingStreamSink implements WebSocketSink {
  /// The channel to which this sink belongs.
  final HtmlWebSocketChannel _channel;

  _HtmlWebSocketSink(HtmlWebSocketChannel channel)
      : _channel = channel,
        super(channel._controller.foreign.sink);

  @override
  Future close([int? closeCode, String? closeReason]) {
    _channel._localCloseCode = closeCode;
    _channel._localCloseReason = closeReason;
    return super.close();
  }
}

/// An enum for choosing what type [HtmlWebSocketChannel] emits for binary
/// messages.
class BinaryType {
  /// Tells the channel to emit binary messages as [Blob]s.
  static const blob = BinaryType._('blob', 'blob');

  /// Tells the channel to emit binary messages as [Uint8List]s.
  static const list = BinaryType._('list', 'arraybuffer');

  /// The name of the binary type, which matches its variable name.
  final String name;

  /// The value as understood by the underlying [WebSocket] API.
  final String value;

  const BinaryType._(this.name, this.value);

  @override
  String toString() => name;
}
