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

void test1(int totalConnections) {
  // Server which just closes immediately.
  HttpServer.bind().then((server) {
    server.listen((HttpRequest request) {
      request.response.close();
    });

    int count = 0;
    HttpClient client = new HttpClient();
    for (int i = 0; i < totalConnections; i++) {
      client.get("127.0.0.1", server.port, "/")
        .then((HttpClientRequest request) => request.close())
        .then((HttpClientResponse response) {
          response.listen((_) {}, onDone: () {
            count++;
            if (count == totalConnections) {
              client.close();
              server.close();
            }
          });
        });
    }
  });
}


void test2(int totalConnections, int outputStreamWrites) {
  // Server which responds without waiting for request body.
  HttpServer.bind().then((server) {
    server.listen((HttpRequest request) {
      request.response.write("!dlrow ,olleH");
      request.response.close();
    });

    int count = 0;
    HttpClient client = new HttpClient();
    for (int i = 0; i < totalConnections; i++) {
      client.get("127.0.0.1", server.port, "/")
        .then((HttpClientRequest request) {
          request.contentLength = -1;
          for (int i = 0; i < outputStreamWrites; i++) {
            request.write("Hello, world!");
          }
          request.done.catchError((_) {});
          return request.close();
        })
        .then((HttpClientResponse response) {
          response.listen(
            (_) {},
            onDone: () {
              count++;
              if (count == totalConnections) {
                client.close(force: true);
                server.close();
              }
            },
            onError: (e) {} /* ignore */);
        })
        .catchError((error) {
          count++;
          if (count == totalConnections) {
            client.close();
            server.close();
          }
        });
    }
  });
}


void test3(int totalConnections) {
  // Server which responds when request body has been received.
  HttpServer.bind().then((server) {

  server.listen((HttpRequest request) {
    request.listen((_) {}, onDone: () {
      request.response.write("!dlrow ,olleH");
      request.response.close();
    });
  });

  int count = 0;
  HttpClient client = new HttpClient();
  for (int i = 0; i < totalConnections; i++) {
    client.get("127.0.0.1", server.port, "/")
      .then((HttpClientRequest request) {
        request.contentLength = -1;
        request.write("Hello, world!");
        return request.close();
      })
      .then((HttpClientResponse response) {
        response.listen((_) {}, onDone: () {
          count++;
          if (count == totalConnections) {
            client.close();
            server.close();
          }
        });
      });
  }

  });
}


void test4() {
  HttpServer.bind().then((server) {

  server.listen((var request) {
    request.listen((_) {}, onDone: () {
      new Timer.periodic(new Duration(milliseconds: 100), (timer) {
        if (server.connectionsInfo().total == 0) {
          server.close();
          timer.cancel();
        }
      });
      request.response.close();
    });
  });

  var client= new HttpClient();
  client.get("127.0.0.1", server.port, "/")
    .then((request) => request.close())
    .then((response) {
      response.listen((_) {}, onDone: () {
        client.close();
      });
    });

  });
}


void test5(int totalConnections) {
  HttpServer.bind().then((server) {
    server.listen(
        (request) {
          request.listen(
              (_) { },
              onDone: () {
                request.response.close();
                request.response.done.catchError((e) {});
              },
              onError: (error) { });
        },
        onError: (error) { });

    // Create a number of client requests and keep then active. Then
    // close the client and wait for the server to lose all active
    // connections.
    var client= new HttpClient();
    for (int i = 0; i < totalConnections; i++) {
      client.post("127.0.0.1", server.port, "/")
        .then((request) {
            request.add([0]);
            // TODO(sgjesse): Make this test work with
            //request.response instead of request.close() return
            //return request.response;
            request.done.catchError((e) {});
            return request.close();
          })
        .then((response) { })
        .catchError((e) { }, test: (e) => e is HttpParserException);
    }
    bool clientClosed = false;
    new Timer.periodic(new Duration(milliseconds: 100), (timer) {
      if (!clientClosed) {
        if (server.connectionsInfo().total == totalConnections) {
          clientClosed = true;
          client.close(force: true);
        }
      } else {
        if (server.connectionsInfo().total == 0) {
          server.close();
          timer.cancel();
        }
      }
    });
  });
}


void main() {
  test1(1);
  test1(10);
  test2(1, 10);
  test2(10, 10);
  test2(10, 1000);
  test3(1);
  test3(10);
  test4();
  test5(1);
  test5(10);
}
