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

  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();
      });
    });
  });
}
