// Copyright (c) 2013, 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.

// @dart = 2.9

import "dart:async";
import "dart:typed_data";
import "dart:io";

import "package:async_helper/async_helper.dart";
import "package:expect/expect.dart";

void testDefaultResponseHeaders() {
  checkDefaultHeaders(headers) {
    Expect.listEquals(
        headers[HttpHeaders.contentTypeHeader], ['text/plain; charset=utf-8']);
    Expect.listEquals(headers['X-Frame-Options'], ['SAMEORIGIN']);
    Expect.listEquals(headers['X-Content-Type-Options'], ['nosniff']);
    Expect.listEquals(headers['X-XSS-Protection'], ['1; mode=block']);
  }

  checkDefaultHeadersClear(headers) {
    Expect.isNull(headers[HttpHeaders.contentTypeHeader]);
    Expect.isNull(headers['X-Frame-Options']);
    Expect.isNull(headers['X-Content-Type-Options']);
    Expect.isNull(headers['X-XSS-Protection']);
  }

  checkDefaultHeadersClearAB(headers) {
    Expect.isNull(headers[HttpHeaders.contentTypeHeader]);
    Expect.isNull(headers['X-Frame-Options']);
    Expect.isNull(headers['X-Content-Type-Options']);
    Expect.isNull(headers['X-XSS-Protection']);
    Expect.listEquals(headers['a'], ['b']);
  }

  test(bool clearHeaders, Map defaultHeaders, Function checker) {
    HttpServer.bind("127.0.0.1", 0).then((server) {
      if (clearHeaders) server.defaultResponseHeaders.clear();
      if (defaultHeaders != null) {
        defaultHeaders.forEach(
            (name, value) => server.defaultResponseHeaders.add(name, value));
      }
      checker(server.defaultResponseHeaders);
      server.listen((request) {
        request.response.close();
      });

      HttpClient client = new HttpClient();
      client
          .get("127.0.0.1", server.port, "/")
          .then((request) => request.close())
          .then((response) {
        checker(response.headers);
        server.close();
        client.close();
      });
    });
  }

  test(false, null, checkDefaultHeaders);
  test(true, null, checkDefaultHeadersClear);
  test(true, {'a': 'b'}, checkDefaultHeadersClearAB);
}

void testDefaultResponseHeadersContentType() {
  test(bool clearHeaders, String requestBody, List<int> responseBody) {
    HttpServer.bind("127.0.0.1", 0).then((server) {
      if (clearHeaders) server.defaultResponseHeaders.clear();
      server.listen((request) {
        request.response.write(requestBody);
        request.response.close();
      });

      HttpClient client = new HttpClient();
      client
          .get("127.0.0.1", server.port, "/")
          .then((request) => request.close())
          .then((response) {
        response.fold([], (a, b) => a..addAll(b)).then((body) {
          Expect.listEquals(body, responseBody);
        }).whenComplete(() {
          server.close();
          client.close();
        });
      });
    });
  }

  test(false, 'æøå', [195, 166, 195, 184, 195, 165]);
  test(true, 'æøå', [230, 248, 229]);
}

void testListenOn() {
  ServerSocket socket;
  HttpServer server;

  void test(void onDone()) {
    Expect.equals(socket.port, server.port);

    HttpClient client = new HttpClient();
    client.get("127.0.0.1", socket.port, "/").then((request) {
      return request.close();
    }).then((response) {
      response.listen((_) {}, onDone: () {
        client.close();
        onDone();
      });
    }).catchError((e, trace) {
      String msg = "Unexpected error in Http Client: $e";
      if (trace != null) msg += "\nStackTrace: $trace";
      Expect.fail(msg);
    });
  }

  // Test two connection after each other.
  asyncStart();
  ServerSocket.bind("127.0.0.1", 0).then((s) {
    socket = s;
    server = new HttpServer.listenOn(socket);
    Expect.equals(server.address.address, '127.0.0.1');
    Expect.equals(server.address.host, '127.0.0.1');
    server.listen((HttpRequest request) {
      request.listen((_) {}, onDone: () => request.response.close());
    });

    test(() {
      test(() {
        server.close();
        Expect.throws(() => server.port);
        Expect.throws(() => server.address);
        socket.close();
        asyncEnd();
      });
    });
  });
}

void testHttpServerZone() {
  asyncStart();
  Expect.equals(Zone.root, Zone.current);
  runZoned(() {
    Expect.notEquals(Zone.root, Zone.current);
    HttpServer.bind("127.0.0.1", 0).then((server) {
      Expect.notEquals(Zone.root, Zone.current);
      server.listen((request) {
        Expect.notEquals(Zone.root, Zone.current);
        request.response.close();
        server.close();
      });
      new HttpClient()
          .get("127.0.0.1", server.port, '/')
          .then((request) => request.close())
          .then((response) => response.drain())
          .then((_) => asyncEnd());
    });
  });
}

void testHttpServerZoneError() {
  asyncStart();
  Expect.equals(Zone.root, Zone.current);
  runZonedGuarded(() {
    Expect.notEquals(Zone.root, Zone.current);
    HttpServer.bind("127.0.0.1", 0).then((server) {
      Expect.notEquals(Zone.root, Zone.current);
      server.listen((request) {
        Expect.notEquals(Zone.root, Zone.current);
        request.listen((_) {}, onError: (error) {
          Expect.notEquals(Zone.root, Zone.current);
          server.close();
          throw error;
        });
      });
      Socket.connect("127.0.0.1", server.port).then((socket) {
        socket.write('GET / HTTP/1.1\r\nContent-Length: 100\r\n\r\n');
        socket.write('some body');
        socket.close();
        socket.listen(null);
      });
    });
  }, (e, s) {
    asyncEnd();
  });
}

void testHttpServerClientClose() {
  HttpServer.bind("127.0.0.1", 0).then((server) {
    runZonedGuarded(() {
      server.listen((request) {
        request.response.bufferOutput = false;
        request.response.add(new Uint8List(64 * 1024));
        new Timer(const Duration(milliseconds: 100), () {
          request.response.close().then((_) {
            server.close();
          });
        });
      });
    }, (e, s) {
      Expect.fail("Unexpected error: $e(${e.hashCode})\n$s");
    });
    var client = new HttpClient();
    client
        .get("127.0.0.1", server.port, "/")
        .then((request) => request.close())
        .then((response) {
      response.listen((_) {}).cancel();
    });
  });
}

void main() {
  testDefaultResponseHeaders();
  testDefaultResponseHeadersContentType();
  testListenOn();
  testHttpServerZone();
  testHttpServerZoneError();
  testHttpServerClientClose();
}
