// Copyright (c) 2014, 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:convert';

import 'package:shelf/shelf.dart';
import 'package:web_socket_channel/web_socket_channel.dart';

/// A class that exposes a handler for upgrading WebSocket requests.
class WebSocketHandler {
  /// The function to call when a request is upgraded.
  final Function _onConnection;

  /// The set of protocols the user supports, or `null`.
  final Set<String> _protocols;

  /// The set of allowed browser origin connections, or `null`..
  final Set<String> _allowedOrigins;

  WebSocketHandler(this._onConnection, this._protocols, this._allowedOrigins);

  /// The [Handler].
  Response handle(Request request) {
    if (request.method != 'GET') return _notFound();

    var connection = request.headers['Connection'];
    if (connection == null) return _notFound();
    var tokens =
        connection.toLowerCase().split(',').map((token) => token.trim());
    if (!tokens.contains('upgrade')) return _notFound();

    var upgrade = request.headers['Upgrade'];
    if (upgrade == null) return _notFound();
    if (upgrade.toLowerCase() != 'websocket') return _notFound();

    var version = request.headers['Sec-WebSocket-Version'];
    if (version == null) {
      return _badRequest('missing Sec-WebSocket-Version header.');
    } else if (version != '13') {
      return _notFound();
    }

    if (request.protocolVersion != '1.1') {
      return _badRequest('unexpected HTTP version '
          '"${request.protocolVersion}".');
    }

    var key = request.headers['Sec-WebSocket-Key'];
    if (key == null) return _badRequest('missing Sec-WebSocket-Key header.');

    if (!request.canHijack) {
      throw new ArgumentError("webSocketHandler may only be used with a server "
          "that supports request hijacking.");
    }

    // The Origin header is always set by browser connections. By filtering out
    // unexpected origins, we ensure that malicious JavaScript is unable to fake
    // a WebSocket handshake.
    var origin = request.headers['Origin'];
    if (origin != null &&
        _allowedOrigins != null &&
        !_allowedOrigins.contains(origin.toLowerCase())) {
      return _forbidden('invalid origin "$origin".');
    }

    var protocol = _chooseProtocol(request);
    request.hijack((channel) {
      var sink = utf8.encoder.startChunkedConversion(channel.sink);
      sink.add("HTTP/1.1 101 Switching Protocols\r\n"
          "Upgrade: websocket\r\n"
          "Connection: Upgrade\r\n"
          "Sec-WebSocket-Accept: ${WebSocketChannel.signKey(key)}\r\n");
      if (protocol != null) sink.add("Sec-WebSocket-Protocol: $protocol\r\n");
      sink.add("\r\n");

      _onConnection(new WebSocketChannel(channel), protocol);
    });

    // [request.hijack] is guaranteed to throw a [HijackException], so we'll
    // never get here.
    assert(false);
    return null;
  }

  /// Selects a subprotocol to use for the given connection.
  ///
  /// If no matching protocol can be found, returns `null`.
  String _chooseProtocol(Request request) {
    var protocols = request.headers['Sec-WebSocket-Protocol'];
    if (protocols == null) return null;
    for (var protocol in protocols.split(',')) {
      protocol = protocol.trim();
      if (_protocols.contains(protocol)) return protocol;
    }
    return null;
  }

  /// Returns a 404 Not Found response.
  Response _notFound() => _htmlResponse(
      404, "404 Not Found", "Only WebSocket connections are supported.");

  /// Returns a 400 Bad Request response.
  ///
  /// [message] will be HTML-escaped before being included in the response body.
  Response _badRequest(String message) => _htmlResponse(
      400, "400 Bad Request", "Invalid WebSocket upgrade request: $message");

  /// Returns a 403 Forbidden response.
  ///
  /// [message] will be HTML-escaped before being included in the response body.
  Response _forbidden(String message) => _htmlResponse(
      403, "403 Forbidden", "WebSocket upgrade refused: $message");

  /// Creates an HTTP response with the given [statusCode] and an HTML body with
  /// [title] and [message].
  ///
  /// [title] and [message] will be automatically HTML-escaped.
  Response _htmlResponse(int statusCode, String title, String message) {
    title = htmlEscape.convert(title);
    message = htmlEscape.convert(message);
    return new Response(statusCode, body: """
      <!doctype html>
      <html>
        <head><title>$title</title></head>
        <body>
          <h1>$title</h1>
          <p>$message</p>
        </body>
      </html>
    """, headers: {'content-type': 'text/html'});
  }
}
