// 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 "dart:isolate";
import "dart:io";
import "package:expect/expect.dart";

class IsolatedHttpServer {
  IsolatedHttpServer();

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

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

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

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

  final _statusPort =
      new ReceivePort(); // 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 {
  // Echo the request content back to the response.
  void _echoHandler(HttpRequest request) {
    var response = request.response;
    Expect.equals("POST", request.method);
    response.contentLength = request.contentLength;
    request.cast<List<int>>().pipe(response);
  }

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

  void init() {
    // Setup request handlers.
    _requestHandlers["/echo"] = _echoHandler;
    _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;
}

void testRead(bool chunkedEncoding) {
  String data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  final int kMessageCount = 10;

  IsolatedHttpServer server = new IsolatedHttpServer();

  void runTest(int port) {
    int count = 0;
    HttpClient httpClient = new HttpClient();
    void sendRequest() {
      httpClient.post("127.0.0.1", port, "/echo").then((request) {
        if (chunkedEncoding) {
          request.write(data.substring(0, 10));
          request.write(data.substring(10, data.length));
        } else {
          request.contentLength = data.length;
          request.add(data.codeUnits);
        }
        return request.close();
      }).then((response) {
        Expect.equals(HttpStatus.ok, response.statusCode);
        List<int> body = <int>[];
        response.listen(body.addAll, onDone: () {
          Expect.equals(data, new String.fromCharCodes(body));
          count++;
          if (count < kMessageCount) {
            sendRequest();
          } else {
            httpClient.close();
            server.shutdown();
          }
        });
      });
    }

    sendRequest();
  }

  server.setServerStartedHandler(runTest);
  server.start(chunkedEncoding);
}

void main() {
  testRead(true);
  testRead(false);
}
