// 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:html';
import 'dart:typed_data';

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

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

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

  @override
  String get protocol => _webSocket.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 => _webSocket.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;

  @override
  Stream get stream => _controller.foreign.stream;
  final _controller =
      StreamChannelController(sync: true, allowForeignErrors: false);

  @override
  WebSocketSink get sink => _sink;
  WebSocketSink _sink;

  /// Creates a new WebSocket connection.
  ///
  /// Connects to [url] using [new WebSocket] 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
  /// [new WebSocket].
  ///
  /// 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(url,
      {Iterable<String> protocols, BinaryType binaryType})
      : this(WebSocket(url.toString(), protocols)
          ..binaryType = (binaryType ?? BinaryType.list).value);

  /// Creates a channel wrapping [webSocket].
  HtmlWebSocketChannel(this._webSocket) {
    _sink = _HtmlWebSocketSink(this);

    if (_webSocket.readyState == WebSocket.OPEN) {
      _listen();
    } else {
      // The socket API guarantees that only a single open event will be
      // emitted.
      _webSocket.onOpen.first.then((_) {
        _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.
    _webSocket.onError.first.then((_) {
      _controller.local.sink
          .addError(WebSocketChannelException('WebSocket connection failed.'));
      _controller.local.sink.close();
    });

    _webSocket.onMessage.listen((event) {
      var data = event.data;
      if (data is ByteBuffer) data = data.asUint8List();
      _controller.local.sink.add(data);
    });

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

  /// Pipes user events to [_webSocket].
  void _listen() {
    _controller.local.stream.listen((message) => _webSocket.send(message),
        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 != null && _localCloseReason != null) {
        _webSocket.close(_localCloseCode, _localCloseReason);
      } else if (_localCloseCode != null) {
        _webSocket.close(_localCloseCode);
      } else {
        _webSocket.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;
}
