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

// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
//
// VMOptions=
// VMOptions=--short_socket_read
// VMOptions=--short_socket_write
// VMOptions=--short_socket_read --short_socket_write

import "package:expect/expect.dart";
import 'dart:async';
import 'dart:io';
import 'dart:isolate';

class IsolatedHttpServer {
  IsolatedHttpServer() : _statusPort = new ReceivePort();

  void setServerStartedHandler(void startedCallback(int port)) {
    _startedCallback = startedCallback;
  }

  void start() {
    ReceivePort receivePort = new ReceivePort();
    var remote = Isolate.spawn(startIsolatedHttpServer, receivePort.sendPort);
    receivePort.first.then((port) {
      _serverPort = port;

      // Send server start message to the server.
      var command = new IsolatedHttpServerCommand.start();
      port.send([command, _statusPort.sendPort]);
    });

    // Handle status messages from the server.
    _statusPort.listen((var status) {
      if (status.isStarted) {
        _startedCallback(status.port);
      }
    });
  }

  void shutdown() {
    // Send server stop message to the server.
    _serverPort
        .send([new IsolatedHttpServerCommand.stop(), _statusPort.sendPort]);
    _statusPort.close();
  }

  void chunkedEncoding() {
    // Send chunked encoding message to the server.
    _serverPort.send([
      new IsolatedHttpServerCommand.chunkedEncoding(),
      _statusPort.sendPort
    ]);
  }

  ReceivePort _statusPort; // Port for receiving messages from the server.
  late SendPort _serverPort; // Port for sending messages to the server.
  var _startedCallback;
}

class IsolatedHttpServerCommand {
  static const START = 0;
  static const STOP = 1;
  static const CHUNKED_ENCODING = 2;

  IsolatedHttpServerCommand.start() : _command = START;
  IsolatedHttpServerCommand.stop() : _command = STOP;
  IsolatedHttpServerCommand.chunkedEncoding() : _command = CHUNKED_ENCODING;

  bool get isStart => _command == START;
  bool get isStop => _command == STOP;
  bool get isChunkedEncoding => _command == CHUNKED_ENCODING;

  int _command;
}

class IsolatedHttpServerStatus {
  static const STARTED = 0;
  static const STOPPED = 1;
  static const ERROR = 2;

  IsolatedHttpServerStatus.started(this._port) : _state = STARTED;
  IsolatedHttpServerStatus.stopped() : _state = STOPPED;
  IsolatedHttpServerStatus.error() : _state = ERROR;

  bool get isStarted => _state == STARTED;
  bool get isStopped => _state == STOPPED;
  bool get isError => _state == ERROR;

  int get port => _port;

  int _state;
  int _port = 0;
}

void startIsolatedHttpServer(Object replyToObj) {
  final replyTo = replyToObj as SendPort;
  var server = new TestServer();
  server.init();
  replyTo.send(server.dispatchSendPort);
}

class TestServer {
  // Return a 404.
  void _notFoundHandler(HttpRequest request) {
    var response = request.response;
    response.statusCode = HttpStatus.notFound;
    response.headers.set("Content-Type", "text/html; charset=UTF-8");
    response.write("Page not found");
    response.close();
  }

  // Check the "Host" header.
  void _hostHandler(HttpRequest request) {
    var response = request.response;
    Expect.equals(1, request.headers["Host"]!.length);
    Expect.equals("www.dartlang.org:1234", request.headers["Host"]![0]);
    Expect.equals("www.dartlang.org", request.headers.host);
    Expect.equals(1234, request.headers.port);
    response.statusCode = HttpStatus.ok;
    response.close();
  }

  // Set the "Expires" header using the expires property.
  void _expires1Handler(HttpRequest request) {
    var response = request.response;
    DateTime date = new DateTime.utc(1999, DateTime.june, 11, 18, 46, 53, 0);
    response.headers.expires = date;
    Expect.equals(date, response.headers.expires);
    response.close();
  }

  // Set the "Expires" header.
  void _expires2Handler(HttpRequest request) {
    var response = request.response;
    response.headers.set("Expires", "Fri, 11 Jun 1999 18:46:53 GMT");
    DateTime date = new DateTime.utc(1999, DateTime.june, 11, 18, 46, 53, 0);
    Expect.equals(date, response.headers.expires);
    response.close();
  }

  void _contentType1Handler(HttpRequest request) {
    var response = request.response;
    Expect.equals("text/html", request.headers.contentType!.value);
    Expect.equals("text", request.headers.contentType!.primaryType);
    Expect.equals("html", request.headers.contentType!.subType);
    Expect.equals("utf-8", request.headers.contentType!.parameters["charset"]);

    ContentType contentType = new ContentType("text", "html", charset: "utf-8");
    response.headers.contentType = contentType;
    response.close();
  }

  void _contentType2Handler(HttpRequest request) {
    var response = request.response;
    Expect.equals("text/html", request.headers.contentType!.value);
    Expect.equals("text", request.headers.contentType!.primaryType);
    Expect.equals("html", request.headers.contentType!.subType);
    Expect.equals("utf-8", request.headers.contentType!.parameters["charset"]);

    response.headers
        .set(HttpHeaders.contentTypeHeader, "text/html;  charset = utf-8");
    response.close();
  }

  void _cookie1Handler(HttpRequest request) {
    var response = request.response;

    // No cookies passed with this request.
    Expect.equals(0, request.cookies.length);

    Cookie cookie1 = new Cookie("name1", "value1");
    DateTime date = new DateTime.utc(2014, DateTime.january, 5, 23, 59, 59, 0);
    cookie1.expires = date;
    cookie1.domain = "www.example.com";
    cookie1.httpOnly = true;
    response.cookies.add(cookie1);
    Cookie cookie2 = new Cookie("name2", "value2");
    cookie2.maxAge = 100;
    cookie2.domain = ".example.com";
    cookie2.path = "/shop";
    response.cookies.add(cookie2);
    response.close();
  }

  void _cookie2Handler(HttpRequest request) {
    var response = request.response;

    // Two cookies passed with this request.
    Expect.equals(2, request.cookies.length);
    response.close();
  }

  void init() {
    // Setup request handlers.
    _requestHandlers["/host"] = _hostHandler;
    _requestHandlers["/expires1"] = _expires1Handler;
    _requestHandlers["/expires2"] = _expires2Handler;
    _requestHandlers["/contenttype1"] = _contentType1Handler;
    _requestHandlers["/contenttype2"] = _contentType2Handler;
    _requestHandlers["/cookie1"] = _cookie1Handler;
    _requestHandlers["/cookie2"] = _cookie2Handler;
    _dispatchPort.listen(dispatch);
  }

  SendPort get dispatchSendPort => _dispatchPort.sendPort;

  void dispatch(message) {
    IsolatedHttpServerCommand command = message[0];
    SendPort replyTo = message[1];
    if (command.isStart) {
      try {
        HttpServer.bind("127.0.0.1", 0).then((server) {
          _server = server;
          _server.listen(_requestReceivedHandler);
          replyTo.send(new IsolatedHttpServerStatus.started(_server.port));
        });
      } catch (e) {
        replyTo.send(new IsolatedHttpServerStatus.error());
      }
    } else if (command.isStop) {
      _server.close();
      _dispatchPort.close();
      replyTo.send(new IsolatedHttpServerStatus.stopped());
    } else if (command.isChunkedEncoding) {
      _chunkedEncoding = true;
    }
  }

  void _requestReceivedHandler(HttpRequest request) {
    var requestHandler = _requestHandlers[request.uri.path];
    if (requestHandler != null) {
      requestHandler(request);
    } else {
      _notFoundHandler(request);
    }
  }

  late HttpServer _server; // HTTP server instance.
  final _dispatchPort = new ReceivePort();
  final _requestHandlers = {};
  bool _chunkedEncoding = false;
}

Future testHost() {
  Completer completer = new Completer();
  IsolatedHttpServer server = new IsolatedHttpServer();
  server.setServerStartedHandler((int port) {
    HttpClient httpClient = new HttpClient();
    httpClient.get("127.0.0.1", port, "/host").then((request) {
      Expect.equals("127.0.0.1:$port", request.headers["host"]![0]);
      request.headers.host = "www.dartlang.com";
      Expect.equals("www.dartlang.com:$port", request.headers["host"]![0]);
      Expect.equals("www.dartlang.com", request.headers.host);
      Expect.equals(port, request.headers.port);
      request.headers.port = 1234;
      Expect.equals("www.dartlang.com:1234", request.headers["host"]![0]);
      Expect.equals(1234, request.headers.port);
      request.headers.port = HttpClient.defaultHttpPort;
      Expect.equals(HttpClient.defaultHttpPort, request.headers.port);
      Expect.equals("www.dartlang.com", request.headers["host"]![0]);
      request.headers.set("Host", "www.dartlang.org");
      Expect.equals("www.dartlang.org", request.headers.host);
      Expect.equals(HttpClient.defaultHttpPort, request.headers.port);
      request.headers.set("Host", "www.dartlang.org:");
      Expect.equals("www.dartlang.org", request.headers.host);
      Expect.equals(HttpClient.defaultHttpPort, request.headers.port);
      request.headers.set("Host", "www.dartlang.org:1234");
      Expect.equals("www.dartlang.org", request.headers.host);
      Expect.equals(1234, request.headers.port);
      return request.close();
    }).then((response) {
      Expect.equals(HttpStatus.ok, response.statusCode);
      response.listen((_) {}, onDone: () {
        httpClient.close();
        server.shutdown();
        completer.complete(true);
      });
    });
  });
  server.start();
  return completer.future;
}

Future testExpires() {
  Completer completer = new Completer();
  IsolatedHttpServer server = new IsolatedHttpServer();
  server.setServerStartedHandler((int port) {
    int responses = 0;
    HttpClient httpClient = new HttpClient();

    void processResponse(HttpClientResponse response) {
      Expect.equals(HttpStatus.ok, response.statusCode);
      Expect.equals(
          "Fri, 11 Jun 1999 18:46:53 GMT", response.headers["expires"]![0]);
      Expect.equals(new DateTime.utc(1999, DateTime.june, 11, 18, 46, 53, 0),
          response.headers.expires);
      response.listen((_) {}, onDone: () {
        responses++;
        if (responses == 2) {
          httpClient.close();
          server.shutdown();
          completer.complete(true);
        }
      });
    }

    httpClient
        .get("127.0.0.1", port, "/expires1")
        .then((request) => request.close())
        .then(processResponse);
    httpClient
        .get("127.0.0.1", port, "/expires2")
        .then((request) => request.close())
        .then(processResponse);
  });
  server.start();
  return completer.future;
}

Future testContentType() {
  Completer completer = new Completer();
  IsolatedHttpServer server = new IsolatedHttpServer();
  server.setServerStartedHandler((int port) {
    int responses = 0;
    HttpClient httpClient = new HttpClient();

    void processResponse(HttpClientResponse response) {
      Expect.equals(HttpStatus.ok, response.statusCode);
      Expect.equals(
          "text/html; charset=utf-8", response.headers.contentType.toString());
      Expect.equals("text/html", response.headers.contentType!.value);
      Expect.equals("text", response.headers.contentType!.primaryType);
      Expect.equals("html", response.headers.contentType!.subType);
      Expect.equals(
          "utf-8", response.headers.contentType!.parameters["charset"]);
      response.listen((_) {}, onDone: () {
        responses++;
        if (responses == 2) {
          httpClient.close();
          server.shutdown();
          completer.complete(true);
        }
      });
    }

    httpClient.get("127.0.0.1", port, "/contenttype1").then((request) {
      request.headers.contentType =
          new ContentType("text", "html", charset: "utf-8");
      return request.close();
    }).then(processResponse);

    httpClient.get("127.0.0.1", port, "/contenttype2").then((request) {
      request.headers
          .set(HttpHeaders.contentTypeHeader, "text/html;  charset = utf-8");
      return request.close();
    }).then(processResponse);
  });
  server.start();
  return completer.future;
}

Future testCookies() {
  Completer completer = new Completer();
  IsolatedHttpServer server = new IsolatedHttpServer();
  server.setServerStartedHandler((int port) {
    int responses = 0;
    HttpClient httpClient = new HttpClient();

    httpClient
        .get("127.0.0.1", port, "/cookie1")
        .then((request) => request.close())
        .then((response) {
      Expect.equals(2, response.cookies.length);
      response.cookies.forEach((cookie) {
        if (cookie.name == "name1") {
          Expect.equals("value1", cookie.value);
          DateTime date =
              new DateTime.utc(2014, DateTime.january, 5, 23, 59, 59, 0);
          Expect.equals(date, cookie.expires);
          Expect.equals("www.example.com", cookie.domain);
          Expect.isTrue(cookie.httpOnly);
        } else if (cookie.name == "name2") {
          Expect.equals("value2", cookie.value);
          Expect.equals(100, cookie.maxAge);
          Expect.equals(".example.com", cookie.domain);
          Expect.equals("/shop", cookie.path);
        } else {
          Expect.fail("Unexpected cookie");
        }
      });

      response.listen((_) {}, onDone: () {
        httpClient.get("127.0.0.1", port, "/cookie2").then((request) {
          request.cookies.add(response.cookies[0]);
          request.cookies.add(response.cookies[1]);
          return request.close();
        }).then((response) {
          response.listen((_) {}, onDone: () {
            httpClient.close();
            server.shutdown();
            completer.complete(true);
          });
        });
      });
    });
  });
  server.start();
  return completer.future;
}

void main() {
  testHost().then((_) {
    return testExpires().then((_) {
      return testContentType().then((_) {
        return testCookies();
      });
    });
  });
}
