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

// 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(),
        _serverPort = null;

  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.
  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;
}

void startIsolatedHttpServer(Object replyToObj) {
  SendPort replyTo = replyToObj;
  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 = new Map();
    _requestHandlers["/host"] = _hostHandler;
    _requestHandlers["/expires1"] = _expires1Handler;
    _requestHandlers["/expires2"] = _expires2Handler;
    _requestHandlers["/contenttype1"] = _contentType1Handler;
    _requestHandlers["/contenttype2"] = _contentType2Handler;
    _requestHandlers["/cookie1"] = _cookie1Handler;
    _requestHandlers["/cookie2"] = _cookie2Handler;
    _dispatchPort = new ReceivePort();
    _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);
    }
  }

  HttpServer _server; // HTTP server instance.
  ReceivePort _dispatchPort;
  Map _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();
      });
    });
  });
}
