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

// @dart = 2.9

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();
  StreamSubscription sub;
  Zone zone;
  int registerCount = 0;
  int callbackBits = 0;
  int stepCount = 0;
  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();
}
