// 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 "dart:async";
import "dart:io";

import "package:async_helper/async_helper.dart";
import "package:expect/expect.dart";

void testCancelResubscribeServerSocket(int socketCount, int backlog) {
  var acceptCount = 0;
  var doneCount = 0;
  var errorCount = 0;
  var earlyErrorCount = 0;

  asyncStart();

  RawServerSocket.bind("127.0.0.1", 0, backlog: backlog).then((server) {
    Expect.isTrue(server.port > 0);

    void checkDone() {
      if (doneCount + errorCount + earlyErrorCount == socketCount) {
        asyncEnd();
        // Be sure to close as subscription.cancel may not be called, if
        // backlog prevents acceptCount to grow to socketCount / 2.
        server.close();
      }
    }

    var subscription;
    subscription = server.listen((client) {
      client.writeEventsEnabled = false;
      client.listen((event) {
        switch (event) {
          case RawSocketEvent.read:
            client.read();
            break;
          case RawSocketEvent.readClosed:
            client.shutdown(SocketDirection.send);
            break;
          case RawSocketEvent.write:
            Expect.fail("No write event expected");
            break;
        }
      });

      if (++acceptCount == socketCount / 2) {
        // Cancel subscription and then attempt to resubscribe.
        subscription.cancel();
        Timer.run(() {
          Expect.throws(() {
            server.listen((_) {
              // Server socket is closed on cancel, so no more events.
              Expect.fail("Event after closed through cancel");
            });
          });
        });
      }
    });

    // Connect a number of sockets.
    for (int i = 0; i < socketCount; i++) {
      RawSocket.connect("127.0.0.1", server.port).then((socket) {
        bool done = false;
        var subscription;
        subscription = socket.listen((event) {
          switch (event) {
            case RawSocketEvent.read:
              Expect.fail("No read event expected");
              break;
            case RawSocketEvent.readClosed:
              done = true;
              doneCount++;
              checkDone();
              break;
            case RawSocketEvent.write:
              // We don't care if this write succeeds, so we don't check
              // the return value (number of bytes written).
              socket.write([1, 2, 3]);
              socket.shutdown(SocketDirection.send);
              break;
          }
        }, onDone: () {
          if (!done) {
            doneCount++;
            checkDone();
          }
        }, onError: (e) {
          // "Connection reset by peer" errors are handled here.
          errorCount++;
          checkDone();
        }, cancelOnError: true);
      }).catchError((e) {
        // "Connection actively refused by host" errors are handled here.
        earlyErrorCount++;
        checkDone();
      });
    }
  });
}

void main() {
  testCancelResubscribeServerSocket(10, 20);
  testCancelResubscribeServerSocket(20, 5);
}
