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

library stream_listen_zeno_test;

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

main() {
  asyncStart();
  var controller;
  for (bool overrideDone in [false, true]) {
    for (bool sync in [false, true]) {
      var mode = "${sync ? "-sync" : ""}${overrideDone ? "-od": ""}";
      controller = new StreamController(sync: sync);
      testStream("SC$mode", controller, controller.stream, overrideDone);
      controller = new StreamController.broadcast(sync: sync);
      testStream("BSC$mode", controller, controller.stream, overrideDone);
      controller = new StreamController(sync: sync);
      testStream("SCAB$mode", controller, controller.stream.asBroadcastStream(),
          overrideDone, 3);
      controller = new StreamController(sync: sync);
      testStream("SCMap$mode", controller, controller.stream.map((x) => x),
          overrideDone, 3);
    }
  }
  asyncEnd();
}

void testStream(
    String name, StreamController controller, Stream stream, bool overrideDone,
    [int registerExpect = 0]) {
  asyncStart();
  late StreamSubscription sub;
  late Zone zone;
  int registerCount = 0;
  int callbackBits = 0;
  int stepCount = 0;
  late void Function() step;
  void nextStep() {
    Zone.root.scheduleMicrotask(step);
  }

  runZoned(() {
    zone = Zone.current;
    sub = stream.listen((v) {
      Expect.identical(zone, Zone.current, name);
      Expect.equals(42, v, name);
      callbackBits |= 1;
      nextStep();
    }, onError: (e, s) {
      Expect.identical(zone, Zone.current, name);
      Expect.equals("ERROR", e, name);
      callbackBits |= 2;
      nextStep();
    }, onDone: () {
      Expect.identical(zone, Zone.current, name);
      if (overrideDone) throw "RUNNING WRONG ONDONE";
      callbackBits |= 4;
      nextStep();
    });
    registerExpect += 3;
    Expect.equals(registerExpect, registerCount, name);
  },
      zoneSpecification: new ZoneSpecification(
          registerCallback: <R>(self, p, z, R callback()) {
        Expect.identical(zone, self, name);
        registerCount++;
        return () {
          Expect.identical(zone, Zone.current, name);
          return callback();
        };
      }, registerUnaryCallback: <R, T>(self, p, z, R callback(T a)) {
        Expect.identical(zone, self, name);
        registerCount++;
        return (a) {
          Expect.identical(zone, Zone.current, name);
          return callback(a);
        };
      }, registerBinaryCallback:
              <R, T1, T2>(self, package, z, R callback(T1 a, T2 b)) {
        Expect.identical(zone, self, name);
        registerCount++;
        return (a, b) {
          Expect.identical(zone, Zone.current, name);
          return callback(a, b);
        };
      }));

  int expectedBits = 0;
  step = () {
    var stepName = "$name-$stepCount";
    Expect.identical(Zone.root, Zone.current, stepName);
    Expect.equals(expectedBits, callbackBits, stepName);
    switch (stepCount++) {
      case 0:
        expectedBits |= 1;
        controller.add(42);
        break;
      case 1:
        expectedBits |= 2;
        controller.addError("ERROR", null);
        break;
      case 2:
        Expect.equals(registerExpect, registerCount, stepName);
        sub.onData((v) {
          Expect.identical(zone, Zone.current, stepName);
          Expect.equals(37, v);
          callbackBits |= 8;
          nextStep();
        });
        Expect.equals(++registerExpect, registerCount, stepName);
        expectedBits |= 8;
        controller.add(37);
        break;
      case 3:
        Expect.equals(registerExpect, registerCount, stepName);
        sub.onError((e, s) {
          Expect.identical(zone, Zone.current);
          Expect.equals("BAD", e);
          callbackBits |= 16;
          nextStep();
        });
        Expect.equals(++registerExpect, registerCount, stepName);
        expectedBits |= 16;
        controller.addError("BAD", null);
        break;
      case 4:
        Expect.equals(registerExpect, registerCount, stepName);
        if (overrideDone) {
          sub.onDone(() {
            Expect.identical(zone, Zone.current);
            callbackBits |= 32;
            nextStep();
          });
          registerExpect++;
          expectedBits |= 32;
        } else {
          expectedBits |= 4;
        }
        Expect.equals(registerExpect, registerCount, stepName);
        controller.close();
        break;
      case 5:
        asyncEnd();
    }
  };
  step();
}
