/*
 * Copyright (c) 2017, 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.
 */
/**
 * @assertion
 * Stream<RawSocketEvent> asBroadcastStream({
 *     void onListen(StreamSubscription<T> subscription),
 *     void onCancel(StreamSubscription<T> subscription)
 * })
 * Returns a multi-subscription stream that produces the same events as this.
 * . . .
 * If onCancel is provided, it is called in a similar way to onListen when the
 * returned stream stops having listener. If it later gets a new listener, the
 * onListen function is called again.
 *
 * @description Checks that if onCancel is provided, it is called in a similar
 * way to onListen when the returned stream stops having listener.
 * @author ngl@unipro.ru
 * @issue 43174
 */
import "dart:async";
import "dart:io";
import "../http_utils.dart";
import "../../../Utils/expect.dart";

var localhost = InternetAddress.loopbackIPv4;

Future<List<RawSocketEvent>> checkOnCancel() async {
  RawDatagramSocket producer = await RawDatagramSocket.bind(localhost, 0);
  RawDatagramSocket receiver = await RawDatagramSocket.bind(localhost, 0);
  List<List<int>> toSend = [[0, 1, 2, 3], [1, 2, 3], [2, 3], [3], [4, 5], [6]];
  List<RawSocketEvent> received = [];
  Completer<List<RawSocketEvent>> completer =
      new Completer<List<RawSocketEvent>>();
  Future<List<RawSocketEvent>> f = completer.future;
  Duration delay = const Duration(seconds: 2);
  int cancel = 0;
  bool anySubscribers = false;

  void onCancel(StreamSubscription<RawSocketEvent> subs) {
    cancel++;
  }

  var mss = receiver.asBroadcastStream(onCancel: onCancel);
  bool wasSent =
      await sendDatagram(producer, toSend, localhost, receiver.port);
  Expect.isTrue(wasSent, "No datagram was sent");

  Expect.equals(0, cancel);

  Future<int> addSubscribers(int n) async {
    if (anySubscribers) {
      Expect.fail('anySubscribers showd be false');
    }
    Completer<int> completer = new Completer<int>();
    Future<int> f = completer.future;
    StreamSubscription? ss;
    anySubscribers = true;

    ss = mss.listen((event) {
      Expect.equals(n - 1, cancel);
      received.add(event);
      receiver.receive();

      if (received.length == 1) {
        ss?.cancel();
        anySubscribers = false;
        if (!completer.isCompleted) {
          receiver.close();
          completer.complete(cancel);
        }
      }
    }, onDone: () {
      anySubscribers = false;
      if (!completer.isCompleted) {
        completer.complete(cancel);
      }
    });

    new Future.delayed(delay, () {
      if (!completer.isCompleted) {
        receiver.close();
        completer.complete(cancel);
        ss?.cancel();
        anySubscribers = false;
      }
    });

    return f;
  }

  await addSubscribers(1);
  Expect.equals(1, cancel);
  await addSubscribers(2);
  Expect.equals(2, cancel);

  new Future.delayed(delay, () {
    if (!completer.isCompleted) {
      Expect.equals(2, cancel);
      completer.complete(received);
    }
  });

  return f;
}

main() async {
  await checkOnCancel();
}
