// 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.onOpen.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.onError.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.onMessage.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.onClose.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;
}
