// 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.

library web_socket_channel.html;

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;

  String get protocol => _webSocket.protocol;

  int get closeCode => _closeCode;
  int _closeCode;

  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;

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

  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);

  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);

  String toString() => name;
}
