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

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

/**
 * We represent the current stack trace by an integer. From time to time we
 * increment the variable. This corresponds to a new stack trace.
 */
int stackTrace = 0;
List restoredStackTrace = [];

List events = [];

ZoneCallback<R> debugZoneRegisterCallback<R>(
  Zone self,
  ZoneDelegate parent,
  Zone origin,
  R f(),
) {
  List savedTrace = [stackTrace]..addAll(restoredStackTrace);
  return parent.registerCallback(origin, () {
    restoredStackTrace = savedTrace;
    return f();
  });
}

ZoneUnaryCallback<R, T> debugZoneRegisterUnaryCallback<R, T>(
  Zone self,
  ZoneDelegate parent,
  Zone origin,
  R f(T arg),
) {
  List savedTrace = [stackTrace]..addAll(restoredStackTrace);
  return parent.registerUnaryCallback(origin, (arg) {
    restoredStackTrace = savedTrace;
    return f(arg);
  });
}

T debugZoneRun<T>(Zone self, ZoneDelegate parent, Zone origin, T f()) {
  stackTrace++;
  restoredStackTrace = [];
  return parent.run(origin, f);
}

R debugZoneRunUnary<R, T>(
  Zone self,
  ZoneDelegate parent,
  Zone origin,
  R f(T arg),
  T arg,
) {
  stackTrace++;
  restoredStackTrace = [];
  return parent.runUnary(origin, f, arg);
}

late List expectedDebugTrace;

void debugUncaughtHandler(
  Zone self,
  ZoneDelegate parent,
  Zone origin,
  error,
  StackTrace? stackTrace,
) {
  events.add("handling uncaught error $error");
  Expect.listEquals(expectedDebugTrace, restoredStackTrace);
  // Suppress the error and don't propagate to parent.
}

const DEBUG_SPECIFICATION = const ZoneSpecification(
  registerCallback: debugZoneRegisterCallback,
  registerUnaryCallback: debugZoneRegisterUnaryCallback,
  run: debugZoneRun,
  runUnary: debugZoneRunUnary,
  handleUncaughtError: debugUncaughtHandler,
);

main() {
  Completer done = new Completer();

  // runGuarded calls run, captures the synchronous error (if any) and
  // gives that one to handleUncaughtError.

  Expect.identical(Zone.root, Zone.current);
  Zone forked;
  forked = Zone.current.fork(specification: DEBUG_SPECIFICATION);

  asyncStart();

  int openTests = 0;

  openTests++;
  forked.run(() {
    int forkTrace = stackTrace;
    scheduleMicrotask(() {
      int scheduleMicrotaskTrace = stackTrace;
      scheduleMicrotask(() {
        expectedDebugTrace = [scheduleMicrotaskTrace, forkTrace];
        openTests--;
        if (openTests == 0) {
          done.complete();
        }
        throw "foo";
      });
      expectedDebugTrace = [forkTrace];
      throw "bar";
    });
  });

  Expect.listEquals([], restoredStackTrace);
  Zone forked2 = forked.fork();
  Zone forked3 = forked2.fork();
  int fork2Trace;
  int fork3Trace;
  var f2;
  var globalTrace = stackTrace;
  var f = forked3.bindCallback(() {
    Expect.identical(forked3, Zone.current);
    fork2Trace = stackTrace;
    f2 = forked2.bindCallback(() {
      Expect.identical(forked2, Zone.current);
      Expect.listEquals([fork2Trace, globalTrace], restoredStackTrace);
      fork3Trace = stackTrace;
      openTests--;
      if (openTests == 0) {
        done.complete();
      }
      scheduleMicrotask(() {
        expectedDebugTrace = [fork3Trace, fork2Trace, globalTrace];
        throw "gee";
      });
    });
  });
  openTests++;
  f();
  f2();

  done.future.whenComplete(() {
    // We don't really care for the order.
    events.sort();
    Expect.listEquals([
      "handling uncaught error bar",
      "handling uncaught error foo",
      "handling uncaught error gee",
    ], events);
    asyncEnd();
  });
}
