// Copyright (c) 2012, 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.

// Patch file for the dart:async library.

import 'dart:_js_helper'
    show
        patch,
        ExceptionAndStackTrace,
        convertDartClosureToJS,
        getTraceFromException,
        requiresPreamble,
        wrapException,
        unwrapException;

import 'dart:_foreign_helper' show JS, JS_GET_FLAG;

import 'dart:_async_await_error_codes' as async_error_codes;

import "dart:collection" show IterableBase;

@patch
class _AsyncRun {
  @patch
  static void _scheduleImmediate(void callback()) {
    _scheduleImmediateClosure(callback);
  }

  // Lazily initialized.
  static final Function _scheduleImmediateClosure =
      _initializeScheduleImmediate();

  static Function _initializeScheduleImmediate() {
    requiresPreamble();
    if (JS('', 'self.scheduleImmediate') != null) {
      return _scheduleImmediateJsOverride;
    }
    if (JS('', 'self.MutationObserver') != null &&
        JS('', 'self.document') != null) {
      // Use mutationObservers.
      var div = JS('', 'self.document.createElement("div")');
      var span = JS('', 'self.document.createElement("span")');
      var storedCallback;

      internalCallback(_) {
        var f = storedCallback;
        storedCallback = null;
        f();
      }

      var observer = JS('', 'new self.MutationObserver(#)',
          convertDartClosureToJS(internalCallback, 1));
      JS('', '#.observe(#, { childList: true })', observer, div);

      return (void callback()) {
        assert(storedCallback == null);
        storedCallback = callback;
        // Because of a broken shadow-dom polyfill we have to change the
        // children instead a cheap property.
        // See https://github.com/Polymer/ShadowDOM/issues/468
        JS('', '#.firstChild ? #.removeChild(#): #.appendChild(#)', div, div,
            span, div, span);
      };
    } else if (JS('', 'self.setImmediate') != null) {
      return _scheduleImmediateWithSetImmediate;
    }
    // TODO(20055): We should use DOM promises when available.
    return _scheduleImmediateWithTimer;
  }

  static void _scheduleImmediateJsOverride(void callback()) {
    internalCallback() {
      callback();
    }

    JS('void', 'self.scheduleImmediate(#)',
        convertDartClosureToJS(internalCallback, 0));
  }

  static void _scheduleImmediateWithSetImmediate(void callback()) {
    internalCallback() {
      callback();
    }

    JS('void', 'self.setImmediate(#)',
        convertDartClosureToJS(internalCallback, 0));
  }

  static void _scheduleImmediateWithTimer(void callback()) {
    Timer._createTimer(Duration.zero, callback);
  }
}

@patch
class DeferredLibrary {
  @patch
  Future<Null> load() {
    throw 'DeferredLibrary not supported. '
        'please use the `import "lib.dart" deferred as lib` syntax.';
  }
}

@patch
class Timer {
  @patch
  static Timer _createTimer(Duration duration, void callback()) {
    int milliseconds = duration.inMilliseconds;
    if (milliseconds < 0) milliseconds = 0;
    return new _TimerImpl(milliseconds, callback);
  }

  @patch
  static Timer _createPeriodicTimer(
      Duration duration, void callback(Timer timer)) {
    int milliseconds = duration.inMilliseconds;
    if (milliseconds < 0) milliseconds = 0;
    return new _TimerImpl.periodic(milliseconds, callback);
  }
}

class _TimerImpl implements Timer {
  final bool _once;
  int _handle;
  int _tick = 0;

  _TimerImpl(int milliseconds, void callback()) : _once = true {
    if (_hasTimer()) {
      void internalCallback() {
        _handle = null;
        this._tick = 1;
        callback();
      }

      _handle = JS('int', 'self.setTimeout(#, #)',
          convertDartClosureToJS(internalCallback, 0), milliseconds);
    } else {
      throw new UnsupportedError('`setTimeout()` not found.');
    }
  }

  _TimerImpl.periodic(int milliseconds, void callback(Timer timer))
      : _once = false {
    if (_hasTimer()) {
      int start = JS('int', 'Date.now()');
      _handle = JS(
          'int',
          'self.setInterval(#, #)',
          convertDartClosureToJS(() {
            int tick = this._tick + 1;
            if (milliseconds > 0) {
              int duration = JS('int', 'Date.now()') - start;
              if (duration > (tick + 1) * milliseconds) {
                tick = duration ~/ milliseconds;
              }
            }
            this._tick = tick;
            callback(this);
          }, 0),
          milliseconds);
    } else {
      throw new UnsupportedError('Periodic timer.');
    }
  }

  @override
  bool get isActive => _handle != null;

  @override
  int get tick => _tick;

  @override
  void cancel() {
    if (_hasTimer()) {
      if (_handle == null) return;
      if (_once) {
        JS('void', 'self.clearTimeout(#)', _handle);
      } else {
        JS('void', 'self.clearInterval(#)', _handle);
      }
      _handle = null;
    } else {
      throw new UnsupportedError('Canceling a timer.');
    }
  }
}

bool _hasTimer() {
  requiresPreamble();
  return JS('', 'self.setTimeout') != null;
}

class _AsyncAwaitCompleter<T> implements Completer<T> {
  final _completer = new Completer<T>.sync();
  bool isSync;

  _AsyncAwaitCompleter() : isSync = false;

  void complete([FutureOr<T> value]) {
    if (isSync) {
      _completer.complete(value);
    } else if (value is Future<T>) {
      value.then(_completer.complete, onError: _completer.completeError);
    } else {
      scheduleMicrotask(() {
        _completer.complete(value);
      });
    }
  }

  void completeError(e, [st]) {
    if (isSync) {
      _completer.completeError(e, st);
    } else {
      scheduleMicrotask(() {
        _completer.completeError(e, st);
      });
    }
  }

  Future<T> get future => _completer.future;
  bool get isCompleted => _completer.isCompleted;
}

/// Creates a Completer for an `async` function.
///
/// Used as part of the runtime support for the async/await transformation.
Completer<T> _makeAsyncAwaitCompleter<T>() {
  return new _AsyncAwaitCompleter<T>();
}

/// Initiates the computation of an `async` function and starts the body
/// synchronously.
///
/// Used as part of the runtime support for the async/await transformation.
///
/// This function sets up the first call into the transformed [bodyFunction].
/// Independently, it takes the [completer] and returns the future of the
/// completer for convenience of the transformed code.
dynamic _asyncStartSync(
    _WrappedAsyncBody bodyFunction, _AsyncAwaitCompleter completer) {
  bodyFunction(async_error_codes.SUCCESS, null);
  completer.isSync = true;
  return completer.future;
}

/// Performs the `await` operation of an `async` function.
///
/// Used as part of the runtime support for the async/await transformation.
///
/// Arranges for [bodyFunction] to be called when the future or value [object]
/// is completed with a code [async_error_codes.SUCCESS] or
/// [async_error_codes.ERROR] depending on the success of the future.
dynamic _asyncAwait(dynamic object, _WrappedAsyncBody bodyFunction) {
  _awaitOnObject(object, bodyFunction);
}

/// Completes the future of an `async` function.
///
/// Used as part of the runtime support for the async/await transformation.
///
/// This function is used when the `async` function returns (explicitly or
/// implicitly).
dynamic _asyncReturn(dynamic object, Completer completer) {
  completer.complete(object);
}

/// Completes the future of an `async` function with an error.
///
/// Used as part of the runtime support for the async/await transformation.
///
/// This function is used when the `async` function re-throws an exception.
dynamic _asyncRethrow(dynamic object, Completer completer) {
  // The error is a js-error.
  completer.completeError(
      unwrapException(object), getTraceFromException(object));
}

/// Awaits on the given [object].
///
/// If the [object] is a Future, registers on it, otherwise wraps it into a
/// future first.
///
/// The [bodyFunction] argument is the continuation that should be invoked
/// when the future completes.
void _awaitOnObject(object, _WrappedAsyncBody bodyFunction) {
  Function thenCallback =
      (result) => bodyFunction(async_error_codes.SUCCESS, result);

  Function errorCallback = (dynamic error, StackTrace stackTrace) {
    ExceptionAndStackTrace wrappedException =
        new ExceptionAndStackTrace(error, stackTrace);
    bodyFunction(async_error_codes.ERROR, wrappedException);
  };

  if (object is _Future) {
    // We can skip the zone registration, since the bodyFunction is already
    // registered (see [_wrapJsFunctionForAsync]).
    object._thenNoZoneRegistration(thenCallback, errorCallback);
  } else if (object is Future) {
    object.then(thenCallback, onError: errorCallback);
  } else {
    _Future future = new _Future();
    future._setValue(object);
    // We can skip the zone registration, since the bodyFunction is already
    // registered (see [_wrapJsFunctionForAsync]).
    future._thenNoZoneRegistration(thenCallback, null);
  }
}

typedef void _WrappedAsyncBody(int errorCode, dynamic result);

_WrappedAsyncBody _wrapJsFunctionForAsync(dynamic /* js function */ function) {
  var protected = JS(
      '',
      """
        (function (fn, ERROR) {
          // Invokes [function] with [errorCode] and [result].
          //
          // If (and as long as) the invocation throws, calls [function] again,
          // with an error-code.
          return function(errorCode, result) {
            while (true) {
              try {
                fn(errorCode, result);
                break;
              } catch (error) {
                result = error;
                errorCode = ERROR;
              }
            }
          }
        })(#, #)""",
      function,
      async_error_codes.ERROR);

  return Zone.current.registerBinaryCallback((int errorCode, dynamic result) {
    JS('', '#(#, #)', protected, errorCode, result);
  });
}

/// Implements the runtime support for async* functions.
///
/// Called by the transformed function for each original return, await, yield,
/// yield* and before starting the function.
///
/// When the async* function wants to return it calls this function with
/// [asyncBody] == [async_error_codes.SUCCESS], the asyncStarHelper takes this
/// as signal to close the stream.
///
/// When the async* function wants to signal that an uncaught error was thrown,
/// it calls this function with [asyncBody] == [async_error_codes.ERROR],
/// the streamHelper takes this as signal to addError [object] to the
/// [controller] and close it.
///
/// If the async* function wants to do a yield or yield*, it calls this function
/// with [object] being an [IterationMarker].
///
/// In the case of a yield or yield*, if the stream subscription has been
/// canceled, schedules [asyncBody] to be called with
/// [async_error_codes.STREAM_WAS_CANCELED].
///
/// If [object] is a single-yield [IterationMarker], adds the value of the
/// [IterationMarker] to the stream. If the stream subscription has been
/// paused, return early. Otherwise schedule the helper function to be
/// executed again.
///
/// If [object] is a yield-star [IterationMarker], starts listening to the
/// yielded stream, and adds all events and errors to our own controller (taking
/// care if the subscription has been paused or canceled) - when the sub-stream
/// is done, schedules [asyncBody] again.
///
/// If the async* function wants to do an await it calls this function with
/// [object] not an [IterationMarker].
///
/// If [object] is not a [Future], it is wrapped in a `Future.value`.
/// The [asyncBody] is called on completion of the future (see [asyncHelper].
void _asyncStarHelper(
    dynamic object,
    dynamic /* int | _WrappedAsyncBody */ bodyFunctionOrErrorCode,
    _AsyncStarStreamController controller) {
  if (identical(bodyFunctionOrErrorCode, async_error_codes.SUCCESS)) {
    // This happens on return from the async* function.
    if (controller.isCanceled) {
      controller.cancelationCompleter.complete();
    } else {
      controller.close();
    }
    return;
  } else if (identical(bodyFunctionOrErrorCode, async_error_codes.ERROR)) {
    // The error is a js-error.
    if (controller.isCanceled) {
      controller.cancelationCompleter.completeError(
          unwrapException(object), getTraceFromException(object));
    } else {
      controller.addError(
          unwrapException(object), getTraceFromException(object));
      controller.close();
    }
    return;
  }

  if (object is _IterationMarker) {
    if (controller.isCanceled) {
      bodyFunctionOrErrorCode(async_error_codes.STREAM_WAS_CANCELED, null);
      return;
    }
    if (object.state == _IterationMarker.YIELD_SINGLE) {
      controller.add(object.value);

      scheduleMicrotask(() {
        if (controller.isPaused) {
          // We only suspend the thread inside the microtask in order to allow
          // listeners on the output stream to pause in response to the just
          // output value, and have the stream immediately stop producing.
          controller.isSuspended = true;
          return;
        }
        bodyFunctionOrErrorCode(null, async_error_codes.SUCCESS);
      });
      return;
    } else if (object.state == _IterationMarker.YIELD_STAR) {
      Stream stream = object.value;
      // Errors of [stream] are passed though to the main stream. (see
      // [AsyncStreamController.addStream]).
      // TODO(sigurdm): The spec is not very clear here. Clarify with Gilad.
      controller.addStream(stream).then((_) {
        // No check for isPaused here because the spec 17.16.2 only
        // demands checks *before* each element in [stream] not after the last
        // one. On the other hand we check for isCanceled, as that check happens
        // after insertion of each element.
        int errorCode = controller.isCanceled
            ? async_error_codes.STREAM_WAS_CANCELED
            : async_error_codes.SUCCESS;
        bodyFunctionOrErrorCode(errorCode, null);
      });
      return;
    }
  }

  _awaitOnObject(object, bodyFunctionOrErrorCode);
}

Stream _streamOfController(_AsyncStarStreamController controller) {
  return controller.stream;
}

/// A wrapper around a [StreamController] that keeps track of the state of
/// the execution of an async* function.
/// It can be in 1 of 3 states:
///
/// - running/scheduled
/// - suspended
/// - canceled
///
/// If yielding while the subscription is paused it will become suspended. And
/// only resume after the subscription is resumed or canceled.
class _AsyncStarStreamController<T> {
  StreamController<T> controller;
  Stream get stream => controller.stream;

  /// True when the async* function has yielded while being paused.
  /// When true execution will only resume after a `onResume` or `onCancel`
  /// event.
  bool isSuspended = false;

  bool get isPaused => controller.isPaused;

  Completer cancelationCompleter = null;

  /// True after the StreamSubscription has been cancelled.
  /// When this is true, errors thrown from the async* body should go to the
  /// [cancelationCompleter] instead of adding them to [controller], and
  /// returning from the async function should complete [cancelationCompleter].
  bool get isCanceled => cancelationCompleter != null;

  add(event) => controller.add(event);

  addStream(Stream<T> stream) {
    return controller.addStream(stream, cancelOnError: false);
  }

  addError(error, stackTrace) => controller.addError(error, stackTrace);

  close() => controller.close();

  _AsyncStarStreamController(_WrappedAsyncBody body) {
    _resumeBody() {
      scheduleMicrotask(() {
        body(async_error_codes.SUCCESS, null);
      });
    }

    controller = new StreamController<T>(onListen: () {
      _resumeBody();
    }, onResume: () {
      // Only schedule again if the async* function actually is suspended.
      // Resume directly instead of scheduling, so that the sequence
      // `pause-resume-pause` will result in one extra event produced.
      if (isSuspended) {
        isSuspended = false;
        _resumeBody();
      }
    }, onCancel: () {
      // If the async* is finished we ignore cancel events.
      if (!controller.isClosed) {
        cancelationCompleter = new Completer();
        if (isSuspended) {
          // Resume the suspended async* function to run finalizers.
          isSuspended = false;
          scheduleMicrotask(() {
            body(async_error_codes.STREAM_WAS_CANCELED, null);
          });
        }
        return cancelationCompleter.future;
      }
    });
  }
}

/// Creates a stream controller for an `async*` function.
///
/// Used as part of the runtime support for the async/await transformation.
_makeAsyncStarStreamController<T>(_WrappedAsyncBody body) {
  return new _AsyncStarStreamController<T>(body);
}

class _IterationMarker {
  static const YIELD_SINGLE = 0;
  static const YIELD_STAR = 1;
  static const ITERATION_ENDED = 2;
  static const UNCAUGHT_ERROR = 3;

  final value;
  final int state;

  const _IterationMarker._(this.state, this.value);

  static yieldStar(dynamic /* Iterable or Stream */ values) {
    return new _IterationMarker._(YIELD_STAR, values);
  }

  static endOfIteration() {
    return const _IterationMarker._(ITERATION_ENDED, null);
  }

  static yieldSingle(dynamic value) {
    return new _IterationMarker._(YIELD_SINGLE, value);
  }

  static uncaughtError(dynamic error) {
    return new _IterationMarker._(UNCAUGHT_ERROR, error);
  }

  toString() => "IterationMarker($state, $value)";
}

class _SyncStarIterator<T> implements Iterator<T> {
  // _SyncStarIterator handles stepping a sync* generator body state machine.
  //
  // It also handles the stepping over 'nested' iterators to flatten yield*
  // statements. For non-sync* iterators, [_nestedIterator] contains the
  // iterator. We delegate to [_nestedIterator] when it is not `null`.
  //
  // For nested sync* iterators, [this] iterator acts on behalf of the innermost
  // nested sync* iterator. The current state machine is suspended on a stack
  // until the inner state machine ends.

  // The state machine for the innermost _SyncStarIterator.
  dynamic _body;

  // The current value, unless iterating a non-sync* nested iterator.
  T _current = null;

  // This is the nested iterator when iterating a yield* of a non-sync iterator.
  // TODO(32956): In strong-mode, yield* takes an Iterable<T> (possibly checked
  // with an implicit downcast), so change type to Iterator<T>.
  Iterator _nestedIterator = null;

  // Stack of suspended state machines when iterating a yield* of a sync*
  // iterator.
  List _suspendedBodies = null;

  _SyncStarIterator(this._body);

  T get current {
    if (_nestedIterator == null) return _current;
    return _nestedIterator.current;
  }

  _runBody() {
    // TODO(sra): Find a way to hard-wire SUCCESS and ERROR codes.
    return JS(
        '',
        '''
        // Invokes [body] with [errorCode] and [result].
        //
        // If (and as long as) the invocation throws, calls [function] again,
        // with an error-code.
        (function(body, SUCCESS, ERROR) {
          var errorValue, errorCode = SUCCESS;
          while (true) {
            try {
              return body(errorCode, errorValue);
            } catch (error) {
              errorValue = error;
              errorCode = ERROR;
            }
          }
        })(#, #, #)''',
        _body,
        async_error_codes.SUCCESS,
        async_error_codes.ERROR);
  }

  bool moveNext() {
    while (true) {
      if (_nestedIterator != null) {
        if (_nestedIterator.moveNext()) {
          return true;
        } else {
          _nestedIterator = null;
        }
      }
      var value = _runBody();
      if (value is _IterationMarker) {
        int state = value.state;
        if (state == _IterationMarker.ITERATION_ENDED) {
          if (_suspendedBodies == null || _suspendedBodies.isEmpty) {
            _current = null;
            // Rely on [_body] to repeatedly return `ITERATION_ENDED`.
            return false;
          }
          // Resume the innermost suspended iterator.
          _body = _suspendedBodies.removeLast();
          continue;
        } else if (state == _IterationMarker.UNCAUGHT_ERROR) {
          // Rely on [_body] to repeatedly return `UNCAUGHT_ERROR`.
          // This is a wrapped exception, so we use JavaScript throw to throw
          // it.
          JS('', 'throw #', value.value);
        } else {
          assert(state == _IterationMarker.YIELD_STAR);
          Iterator inner = value.value.iterator;
          if (inner is _SyncStarIterator) {
            // Suspend the current state machine and start acting on behalf of
            // the nested state machine.
            //
            // TODO(sra): Recognize "tail yield*" statements and avoid
            // suspending the current body when all it will do is step without
            // effect to ITERATION_ENDED.
            (_suspendedBodies ??= []).add(_body);
            _body = inner._body;
            continue;
          } else {
            _nestedIterator = inner;
            // TODO(32956): Change to the following when strong-mode is the only
            // option:
            //
            //     _nestedIterator = JS<Iterator<T>>('','#', inner);
            continue;
          }
        }
      } else {
        // TODO(32956): Remove this test.
        _current = JS<T>('', '#', value);
        return true;
      }
    }
    return false; // TODO(sra): Fix type inference so that this is not needed.
  }
}

/// Creates an Iterable for a `sync*` function.
///
/// Used as part of the runtime support for the async/await transformation.
_SyncStarIterable<T> _makeSyncStarIterable<T>(body) {
  return new _SyncStarIterable<T>(body);
}

/// An Iterable corresponding to a sync* method.
///
/// Each invocation of a sync* method will return a new instance of this class.
class _SyncStarIterable<T> extends IterableBase<T> {
  // This is a function that will return a helper function that does the
  // iteration of the sync*.
  //
  // Each invocation should give a body with fresh state.
  final dynamic /* js function */ _outerHelper;

  _SyncStarIterable(this._outerHelper);

  Iterator<T> get iterator =>
      new _SyncStarIterator<T>(JS('', '#()', _outerHelper));
}

@patch
void _rethrow(Object error, StackTrace stackTrace) {
  error = wrapException(error);
  JS('void', '#.stack = #', error, stackTrace.toString());
  JS('void', 'throw #', error);
}
