// 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:async';
import 'dart:io';

import 'src/multi_headers.dart';
import 'src/utils.dart';

/// The error code for an error caused by a port already being in use.
final _addressInUseErrno = _computeAddressInUseErrno();
int _computeAddressInUseErrno() {
  if (Platform.isWindows) return 10048;
  if (Platform.isMacOS) return 48;
  assert(Platform.isLinux);
  return 98;
}

/// An implementation of `dart:io`'s [HttpServer] that wraps multiple servers
/// and forwards methods to all of them.
///
/// This is useful for serving the same application on multiple network
/// interfaces while still having a unified way of controlling the servers. In
/// particular, it supports serving on both the IPv4 and IPv6 loopback addresses
/// using [HttpMultiServer.loopback].
class HttpMultiServer extends StreamView<HttpRequest> implements HttpServer {
  /// The wrapped servers.
  final Set<HttpServer> _servers;

  /// Returns the default value of the `Server` header for all responses
  /// generated by each server.
  ///
  /// If the wrapped servers have different default values, it's not defined
  /// which value is returned.
  String get serverHeader => _servers.first.serverHeader;
  set serverHeader(String value) {
    for (var server in _servers) {
      server.serverHeader = value;
    }
  }

  /// Returns the default set of headers added to all response objects.
  ///
  /// If the wrapped servers have different default headers, it's not defined
  /// which header is returned for accessor methods.
  final HttpHeaders defaultResponseHeaders;

  Duration get idleTimeout => _servers.first.idleTimeout;
  set idleTimeout(Duration value) {
    for (var server in _servers) {
      server.idleTimeout = value;
    }
  }

  bool get autoCompress => _servers.first.autoCompress;
  set autoCompress(bool value) {
    for (var server in _servers) {
      server.autoCompress = value;
    }
  }

  /// Returns the port that one of the wrapped servers is listening on.
  ///
  /// If the wrapped servers are listening on different ports, it's not defined
  /// which port is returned.
  int get port => _servers.first.port;

  /// Returns the address that one of the wrapped servers is listening on.
  ///
  /// If the wrapped servers are listening on different addresses, it's not
  /// defined which address is returned.
  InternetAddress get address => _servers.first.address;

  set sessionTimeout(int value) {
    for (var server in _servers) {
      server.sessionTimeout = value;
    }
  }

  /// Creates an [HttpMultiServer] wrapping [servers].
  ///
  /// All [servers] should have the same configuration and none should be
  /// listened to when this is called.
  HttpMultiServer(Iterable<HttpServer> servers)
      : _servers = servers.toSet(),
        defaultResponseHeaders = new MultiHeaders(
            servers.map((server) => server.defaultResponseHeaders)),
        super(mergeStreams(servers));

  /// Creates an [HttpServer] listening on all available loopback addresses for
  /// this computer.
  ///
  /// See [HttpServer.bind].
  static Future<HttpServer> loopback(int port, {int backlog, bool v6Only: false,
        bool shared: false}) {
    if (backlog == null) backlog = 0;

    return _loopback(port, (address, port) =>
        HttpServer.bind(address, port,
            backlog: backlog, v6Only: v6Only, shared: shared));
  }

  /// Like [loopback], but supports HTTPS requests.
  ///
  /// See [HttpServer.bindSecure].
  static Future<HttpServer> loopbackSecure(int port, SecurityContext context,
      {int backlog, bool v6Only: false, bool requestClientCertificate: false,
      bool shared: false}) {
    if (backlog == null) backlog = 0;

    return _loopback(port, (address, port) =>
        HttpServer.bindSecure(address, port, context,
            backlog: backlog, v6Only: v6Only, shared: shared,
            requestClientCertificate: requestClientCertificate));
  }

  /// A helper method for initializing loopback servers.
  ///
  /// [bind] should forward to either [HttpServer.bind] or
  /// [HttpServer.bindSecure].
  static Future<HttpServer> _loopback(int port,
      Future<HttpServer> bind(InternetAddress address, int port),
      [int remainingRetries]) {
    if (remainingRetries == null) remainingRetries = 5;

    return Future.wait([
      supportsIpV6,
      bind(InternetAddress.LOOPBACK_IP_V4, port)
    ]).then((results) {
      var supportsIpV6 = results[0];
      var v4Server = results[1];

      if (!supportsIpV6) return v4Server;

      // Reuse the IPv4 server's port so that if [port] is 0, both servers use
      // the same ephemeral port.
      return bind(InternetAddress.LOOPBACK_IP_V6, v4Server.port)
          .then((v6Server) {
        return new HttpMultiServer([v4Server, v6Server]);
      }).catchError((error) {
        if (error is! SocketException) throw error;
        if (error.osError.errorCode != _addressInUseErrno) throw error;
        if (port != 0) throw error;
        if (remainingRetries == 0) throw error;

        // A port being available on IPv4 doesn't necessarily mean that the same
        // port is available on IPv6. If it's not (which is rare in practice),
        // we try again until we find one that's available on both.
        v4Server.close();
        return _loopback(port, bind, remainingRetries - 1);
      });
    });
  }

  Future close({bool force: false}) =>
      Future.wait(_servers.map((server) => server.close(force: force)));

  /// Returns an HttpConnectionsInfo object summarizing the total number of
  /// current connections handled by all the servers.
  HttpConnectionsInfo connectionsInfo() {
    var info = new HttpConnectionsInfo();
    for (var server in _servers) {
      var subInfo = server.connectionsInfo();
      info.total += subInfo.total;
      info.active += subInfo.active;
      info.idle += subInfo.idle;
      info.closing += subInfo.closing;
    }
    return info;
  }
}
