// 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=
// 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 {
    _serverPort = spawnFunction(startIsolatedHttpServer);
  }

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

  void start() {
    // Handle status messages from the server.
    _statusPort.receive((var status, SendPort replyTo) {
      if (status.isStarted) {
        _startedCallback(status.port);
      }
    });

    // Send server start message to the server.
    var command = new IsolatedHttpServerCommand.start();
    _serverPort.send(command, _statusPort.toSendPort());
  }

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

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

  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() {
  var server = new TestServer();
  server.init();
  port.receive(server.dispatch);
}


class TestServer {
  // Return a 404.
  void _notFoundHandler(HttpRequest request) {
    var response = request.response;
    response.statusCode = HttpStatus.NOT_FOUND;
    response.headers.set("Content-Type", "text/html; charset=UTF-8");
    response.outputStream.writeString("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.CONTENT_TYPE,
                         "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;
  }

  void dispatch(message, replyTo) {
    if (message.isStart) {
      try {
        HttpServer.bind("127.0.0.1", 0).then((server) {
          _server = server;
          _server.listen(_requestReceivedHandler);
          replyTo.send(new IsolatedHttpServerStatus.started(_server.port),
                       null);
        });
      } catch (e) {
        replyTo.send(new IsolatedHttpServerStatus.error(), null);
      }
    } else if (message.isStop) {
      _server.close();
      port.close();
      replyTo.send(new IsolatedHttpServerStatus.stopped(), null);
    } else if (message.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.
  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.DEFAULT_HTTP_PORT;
          Expect.equals(HttpClient.DEFAULT_HTTP_PORT, 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.DEFAULT_HTTP_PORT, request.headers.port);
          request.headers.set("Host", "www.dartlang.org:");
          Expect.equals("www.dartlang.org", request.headers.host);
          Expect.equals(HttpClient.DEFAULT_HTTP_PORT, 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.CONTENT_TYPE,
                              "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();
      });
    });
  });
}
