// 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 'package:http/http.dart' as http;
import 'package:http_multi_server/http_multi_server.dart';
import 'package:http_multi_server/src/utils.dart';
import 'package:test/test.dart';

void main() {
  group("with multiple HttpServers", () {
    var multiServer;
    var subServer1;
    var subServer2;
    var subServer3;
    setUp(() {
      return Future.wait([
        HttpServer.bind("127.0.0.1", 0).then((server) => subServer1 = server),
        HttpServer.bind("127.0.0.1", 0).then((server) => subServer2 = server),
        HttpServer.bind("127.0.0.1", 0).then((server) => subServer3 = server)
      ]).then((servers) => multiServer = new HttpMultiServer(servers));
    });

    tearDown(() => multiServer.close());

    test("listen listens to all servers", () {
      multiServer.listen((request) {
        request.response.write("got request");
        request.response.close();
      });

      expect(_read(subServer1), completion(equals("got request")));
      expect(_read(subServer2), completion(equals("got request")));
      expect(_read(subServer3), completion(equals("got request")));
    });

    test("serverHeader= sets the value for all servers", () {
      multiServer.serverHeader = "http_multi_server test";

      multiServer.listen((request) {
        request.response.write("got request");
        request.response.close();
      });

      expect(_get(subServer1).then((response) {
        expect(response.headers['server'], equals("http_multi_server test"));
      }), completes);

      expect(_get(subServer2).then((response) {
        expect(response.headers['server'], equals("http_multi_server test"));
      }), completes);

      expect(_get(subServer3).then((response) {
        expect(response.headers['server'], equals("http_multi_server test"));
      }), completes);
    });

    test("autoCompress= sets the value for all servers", () {
      multiServer.autoCompress = true;

      multiServer.listen((request) {
        request.response.write("got request");
        request.response.close();
      });

      expect(_get(subServer1).then((response) {
        expect(response.headers['content-encoding'], equals("gzip"));
      }), completes);

      expect(_get(subServer2).then((response) {
        expect(response.headers['content-encoding'], equals("gzip"));
      }), completes);

      expect(_get(subServer3).then((response) {
        expect(response.headers['content-encoding'], equals("gzip"));
      }), completes);
    });

    test("headers.set sets the value for all servers", () {
      multiServer.defaultResponseHeaders.set(
          "server", "http_multi_server test");

      multiServer.listen((request) {
        request.response.write("got request");
        request.response.close();
      });

      expect(_get(subServer1).then((response) {
        expect(response.headers['server'], equals("http_multi_server test"));
      }), completes);

      expect(_get(subServer2).then((response) {
        expect(response.headers['server'], equals("http_multi_server test"));
      }), completes);

      expect(_get(subServer3).then((response) {
        expect(response.headers['server'], equals("http_multi_server test"));
      }), completes);
    });

    test("connectionsInfo sums the values for all servers", () {
      var pendingRequests = 0;
      var awaitingResponseCompleter = new Completer();
      var sendResponseCompleter = new Completer();
      multiServer.listen((request) {
        sendResponseCompleter.future.then((_) {
          request.response.write("got request");
          request.response.close();
        });

        pendingRequests++;
        if (pendingRequests == 2) awaitingResponseCompleter.complete();
      });

      // Queue up some requests, then wait on [awaitingResponseCompleter] to
      // make sure they're in-flight before we check [connectionsInfo].
      expect(_get(subServer1), completes);
      expect(_get(subServer2), completes);

      return awaitingResponseCompleter.future.then((_) {
        var info = multiServer.connectionsInfo();
        expect(info.total, equals(2));
        expect(info.active, equals(2));
        expect(info.idle, equals(0));
        expect(info.closing, equals(0));

        sendResponseCompleter.complete();
      });
    });
  });

  group("HttpMultiServer.loopback", () {
    var server;
    setUp(() {
      return HttpMultiServer.loopback(0).then((server_) => server = server_);
    });

    tearDown(() => server.close());

    test("listens on all localhost interfaces", () {
      server.listen((request) {
        request.response.write("got request");
        request.response.close();
      });

      expect(http.read("http://127.0.0.1:${server.port}/"),
          completion(equals("got request")));

      return supportsIpV6.then((supportsIpV6) {
        if (!supportsIpV6) return;
        expect(http.read("http://[::1]:${server.port}/"),
            completion(equals("got request")));
      });
    });
  });
}

/// Makes a GET request to the root of [server] and returns the response.
Future<http.Response> _get(HttpServer server) => http.get(_urlFor(server));

/// Makes a GET request to the root of [server] and returns the response body.
Future<String> _read(HttpServer server) => http.read(_urlFor(server));

/// Returns the URL for the root of [server].
String _urlFor(HttpServer server) =>
    "http://${server.address.host}:${server.port}/";
