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

part of $LIBRARYNAME;

typedef void RemoveFrameRequestMapping(int id);

/**
 * The task object representing animation-frame requests.
 *
 * For historical reasons, [Window.requestAnimationFrame] returns an integer
 * to users. However, zone tasks must be unique objects, and an integer can
 * therefore not be used as task object. The [Window] class thus keeps a mapping
 * from the integer ID to the corresponding task object. All zone related
 * operations work on this task object, whereas users of
 * [Window.requestAnimationFrame] only see the integer ID.
 *
 * Since this mapping takes up space, it must be removed when the
 * animation-frame task has triggered. The default implementation does this
 * automatically, but intercepting implementations of `requestAnimationFrame`
 * must make sure to call the [AnimationFrameTask.removeMapping]
 * function that is provided in the task specification.
 *
 * *Experimental*. This class may disappear without notice.
 */
abstract class AnimationFrameTask {
  /** The ID that is returned to users. */
  int get id;

  /** The zone in which the task will run. */
  Zone get zone;

  /**
   * Cancels the animation-frame request.
   *
   * A call to [Window.cancelAnimationFrame] with an `id` argument equal to [id]
   * forwards the request to this function.
   *
   * Zones that intercept animation-frame requests implement this method so
   * that they can react to cancelation requests.
   */
  void cancel(Window window);

  /**
   * Maps animation-frame request IDs to their task objects.
   */
  static final Map<int, _AnimationFrameTask> _tasks = {};

  /**
   * Removes the mapping from [id] to [AnimationFrameTask].
   *
   * This function must be invoked by user-implemented animation-frame
   * tasks, before running [callback].
   *
   * See [AnimationFrameTask].
   */
  static void removeMapping(int id) {
    _tasks.remove(id);
  }
}

class _AnimationFrameTask implements AnimationFrameTask {
  final int id;
  final Zone zone;
  final FrameRequestCallback _callback;

  _AnimationFrameTask(this.id, this.zone, this._callback);

  void cancel(Window window) {
    window._cancelAnimationFrame(this.id);
  }
}

/**
 * The task specification for an animation-frame request.
 *
 * *Experimental*. This class may disappear without notice.
 */
class AnimationFrameRequestSpecification implements TaskSpecification {
  /**
   * The window on which [Window.requestAnimationFrame] was invoked.
   */
  final Window window;

  /**
   * The callback that is executed when the animation-frame is ready.
   *
   * Note that the callback hasn't been registered in any zone when the `create`
   * function (passed to [Zone.createTask]) is invoked.
   */
  final FrameRequestCallback callback;

  AnimationFrameRequestSpecification(this.window, this.callback);

  String get name => "dart.html.request-animation-frame";
  bool get isOneShot => true;
}

@DocsEditable()
$if DART2JS
$(ANNOTATIONS)@Native("Window,DOMWindow")
$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS {
$else
$(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS {
$endif

  /**
   * Returns a Future that completes just before the window is about to
   * repaint so the user can draw an animation frame.
   *
   * If you need to later cancel this animation, use [requestAnimationFrame]
   * instead.
   *
   * The [Future] completes to a timestamp that represents a floating
   * point value of the number of milliseconds that have elapsed since the page
   * started to load (which is also the timestamp at this call to
   * animationFrame).
   *
   * Note: The code that runs when the future completes should call
   * [animationFrame] again for the animation to continue.
   */
  Future<num> get animationFrame {
    var completer = new Completer<num>.sync();
    requestAnimationFrame(completer.complete);
    return completer.future;
  }

$if DART2JS
  /**
   * The newest document in this window.
   *
   * ## Other resources
   *
   * * [Loading web
   *   pages](https://html.spec.whatwg.org/multipage/browsers.html)
   *   from WHATWG.
   */
  Document get document => JS('Document', '#.document', this);

  WindowBase _open2(url, name) =>
      JS('Window|Null', '#.open(#,#)', this, url, name);

  WindowBase _open3(url, name, options) =>
      JS('Window|Null', '#.open(#,#,#)', this, url, name, options);

  /**
   * Opens a new window.
   *
   * ## Other resources
   *
   * * [Window.open](https://developer.mozilla.org/en-US/docs/Web/API/Window.open)
   *   from MDN.
   * * [Window open](http://docs.webplatform.org/wiki/dom/methods/open)
   *   from WebPlatform.org.
   */
  WindowBase open(String url, String name, [String options]) {
    if (options == null) {
      return _DOMWindowCrossFrame._createSafe(_open2(url, name));
    } else {
      return _DOMWindowCrossFrame._createSafe(_open3(url, name, options));
    }
  }

  // API level getter and setter for Location.
  // TODO: The cross domain safe wrapper can be inserted here.
  /**
   * The current location of this window.
   *
   *     Location currentLocation = window.location;
   *     print(currentLocation.href); // 'http://www.example.com:80/'
   */
  Location get location => _location;

  // TODO: consider forcing users to do: window.location.assign('string').
  /**
   * Sets the window's location, which causes the browser to navigate to the new
   * location. [value] may be a Location object or a String.
   */
  set location(value) {
    _location = value;
  }

  // Native getter and setter to access raw Location object.
  dynamic get _location => JS('Location|Null', '#.location', this);
  set _location(value) {
    JS('void', '#.location = #', this, value);
  }

$endif

  /**
   * Called to draw an animation frame and then request the window to repaint
   * after [callback] has finished (creating the animation).
   *
   * Use this method only if you need to later call [cancelAnimationFrame]. If
   * not, the preferred Dart idiom is to set animation frames by calling
   * [animationFrame], which returns a Future.
   *
   * Returns a non-zero valued integer to represent the request id for this
   * request. This value only needs to be saved if you intend to call
   * [cancelAnimationFrame] so you can specify the particular animation to
   * cancel.
   *
   * Note: The supplied [callback] needs to call [requestAnimationFrame] again
   * for the animation to continue.
   */
  @DomName('Window.requestAnimationFrame')
  int requestAnimationFrame(FrameRequestCallback callback) {
$if DART2JS
    _ensureRequestAnimationFrame();
$endif
    if (identical(Zone.current, Zone.ROOT)) {
      return _requestAnimationFrame(callback);
    }
    var spec = new AnimationFrameRequestSpecification(this, callback);
    var task = Zone.current.createTask/*<AnimationFrameTask>*/(
        _createAnimationFrameTask, spec);
    AnimationFrameTask._tasks[task.id] = task;
    return task.id;
  }

  static _AnimationFrameTask _createAnimationFrameTask(
      AnimationFrameRequestSpecification spec, Zone zone) {
    var task;
    var id = spec.window._requestAnimationFrame((num time) {
      AnimationFrameTask.removeMapping(task.id);
      zone.runTask(_runAnimationFrame, task, time);
    });
    var callback = zone.registerUnaryCallback(spec.callback);
    task = new _AnimationFrameTask(id, zone, callback);
    return task;
  }

  static void _runAnimationFrame(_AnimationFrameTask task, num time) {
    task._callback(time);
  }

  /**
   * Cancels an animation frame request.
   *
   * ## Other resources
   *
   * * [Window.cancelAnimationFrame](https://developer.mozilla.org/en-US/docs/Web/API/Window.cancelAnimationFrame)
   *   from MDN.
   */
  @DomName('Window.cancelAnimationFrame')
  void cancelAnimationFrame(int id) {
$if DART2JS
    _ensureRequestAnimationFrame();
$endif
    var task = AnimationFrameTask._tasks.remove(id);
    if (task == null) {
      // Assume that the animation frame request wasn't intercepted by a zone.
      _cancelAnimationFrame(id);
      return;
    }
    task.cancel(this);
  }

$if DART2JS
  @JSName('requestAnimationFrame')
  int _requestAnimationFrame(FrameRequestCallback callback) native;

  @JSName('cancelAnimationFrame')
  void _cancelAnimationFrame(int id) native;

  _ensureRequestAnimationFrame() {
    if (JS('bool',
           '!!(#.requestAnimationFrame && #.cancelAnimationFrame)', this, this))
      return;

    JS('void',
       r"""
  (function($this) {
   var vendors = ['ms', 'moz', 'webkit', 'o'];
   for (var i = 0; i < vendors.length && !$this.requestAnimationFrame; ++i) {
     $this.requestAnimationFrame = $this[vendors[i] + 'RequestAnimationFrame'];
     $this.cancelAnimationFrame =
         $this[vendors[i]+'CancelAnimationFrame'] ||
         $this[vendors[i]+'CancelRequestAnimationFrame'];
   }
   if ($this.requestAnimationFrame && $this.cancelAnimationFrame) return;
   $this.requestAnimationFrame = function(callback) {
      return window.setTimeout(function() {
        callback(Date.now());
      }, 16 /* 16ms ~= 60fps */);
   };
   $this.cancelAnimationFrame = function(id) { clearTimeout(id); }
  })(#)""",
       this);
  }

  /**
   * Gets an instance of the Indexed DB factory to being using Indexed DB.
   *
   * Use [indexed_db.IdbFactory.supported] to check if Indexed DB is supported on the
   * current platform.
   */
  @SupportedBrowser(SupportedBrowser.CHROME, '23.0')
  @SupportedBrowser(SupportedBrowser.FIREFOX, '15.0')
  @SupportedBrowser(SupportedBrowser.IE, '10.0')
  @Experimental()
  IdbFactory get indexedDB =>
      JS('IdbFactory|Null',  // If not supported, returns null.
         '#.indexedDB || #.webkitIndexedDB || #.mozIndexedDB',
         this, this, this);

  /// The debugging console for this window.
  @DomName('Window.console')
  Console get console => Console._safeConsole;
$endif

  /**
   * Access a sandboxed file system of the specified `size`. If `persistent` is
   * true, the application will request permission from the user to create
   * lasting storage. This storage cannot be freed without the user's
   * permission. Returns a [Future] whose value stores a reference to the
   * sandboxed file system for use. Because the file system is sandboxed,
   * applications cannot access file systems created in other web pages.
   */
  Future<FileSystem> requestFileSystem(int size, {bool persistent: false}) {
    return _requestFileSystem(persistent? 1 : 0, size);
  }

  /**
   * convertPointFromNodeToPage and convertPointFromPageToNode are removed.
   * see http://dev.w3.org/csswg/cssom-view/#geometry
   */
  static bool get supportsPointConversions => DomPoint.supported;
$!MEMBERS

  /**
   * Static factory designed to expose `beforeunload` events to event
   * handlers that are not necessarily instances of [Window].
   *
   * See [EventStreamProvider] for usage information.
   */
  @DomName('Window.beforeunloadEvent')
  static const EventStreamProvider<BeforeUnloadEvent> beforeUnloadEvent =
      const _BeforeUnloadEventStreamProvider('beforeunload');

  /// Stream of `beforeunload` events handled by this [Window].
  @DomName('Window.onbeforeunload')
  Stream<Event> get onBeforeUnload => beforeUnloadEvent.forTarget(this);

  /**
   * Moves this window to a specific position.
   *
   * x and y can be negative.
   *
   * ## Other resources
   *
   * * [Window.moveTo](https://developer.mozilla.org/en-US/docs/Web/API/Window.moveTo)
   *   from MDN.
   * * [Window.moveTo](http://dev.w3.org/csswg/cssom-view/#dom-window-moveto)
   *   from W3C.
   */
  void moveTo(Point p) {
    _moveTo(p.x, p.y);
  }

$if DART2JS
  @DomName('Window.pageXOffset')
  @DocsEditable()
  int get pageXOffset => JS('num', '#.pageXOffset', this).round();

  @DomName('Window.pageYOffset')
  @DocsEditable()
  int get pageYOffset => JS('num', '#.pageYOffset', this).round();

  /**
   * The distance this window has been scrolled horizontally.
   *
   * ## Other resources
   *
   * * [The Screen interface
   *   specification](http://www.w3.org/TR/cssom-view/#screen) from W3C.
   * * [scrollX](https://developer.mozilla.org/en-US/docs/Web/API/Window.scrollX)
   *   from MDN.
   */
  @DomName('Window.scrollX')
  @DocsEditable()
  int get scrollX => JS('bool', '("scrollX" in #)', this) ?
      JS('num', '#.scrollX', this).round() :
      document.documentElement.scrollLeft;

  /**
   * The distance this window has been scrolled vertically.
   *
   * ## Other resources
   *
   * * [The Screen interface
   *   specification](http://www.w3.org/TR/cssom-view/#screen) from W3C.
   * * [scrollY](https://developer.mozilla.org/en-US/docs/Web/API/Window.scrollY)
   *   from MDN.
   */
  @DomName('Window.scrollY')
  @DocsEditable()
  int get scrollY => JS('bool', '("scrollY" in #)', this) ?
      JS('num', '#.scrollY', this).round() :
      document.documentElement.scrollTop;
$else
  @DomName('Window.pageXOffset')
  @DocsEditable()
  int get pageXOffset => _blink.BlinkWindow.instance.pageXOffset_Getter_(this).round();

  @DomName('Window.pageYOffset')
  @DocsEditable()
  int get pageYOffset => _blink.BlinkWindow.instance.pageYOffset_Getter_(this).round();

  @DomName('Window.scrollX')
  @DocsEditable()
  int get scrollX => _blink.BlinkWindow.instance.scrollX_Getter_(this).round();

  @DomName('Window.scrollY')
  @DocsEditable()
  int get scrollY => _blink.BlinkWindow.instance.scrollY_Getter_(this).round();
$endif
}

$if DART2JS
class _BeforeUnloadEvent extends _WrappedEvent implements BeforeUnloadEvent {
  String _returnValue;

  _BeforeUnloadEvent(Event base): super(base);

  String get returnValue => _returnValue;

  set returnValue(String value) {
    _returnValue = value;
    // FF and IE use the value as the return value, Chrome will return this from
    // the event callback function.
    if (JS('bool', '("returnValue" in #)', wrapped)) {
      JS('void', '#.returnValue = #', wrapped, value);
    }
  }
}
$endif

class _BeforeUnloadEventStreamProvider implements
    EventStreamProvider<BeforeUnloadEvent> {
  final String _eventType;

  const _BeforeUnloadEventStreamProvider(this._eventType);

  Stream<BeforeUnloadEvent> forTarget(EventTarget e, {bool useCapture: false}) {
$if DART2JS
    // Specify the generic type for EventStream only in dart2js to avoid
    // checked mode errors in dartium.
    var stream = new _EventStream<BeforeUnloadEvent>(e, _eventType, useCapture);
    var controller = new StreamController<BeforeUnloadEvent>(sync: true);

    stream.listen((event) {
      var wrapped = new _BeforeUnloadEvent(event);
      controller.add(wrapped);
    });

    return controller.stream;
$else
    var stream = new _EventStream(e, _eventType, useCapture);
    return stream;
$endif
  }

  String getEventType(EventTarget target) {
    return _eventType;
  }

  ElementStream<BeforeUnloadEvent> forElement(Element e, {bool useCapture: false}) {
$if DART2JS
    // Specify the generic type for _ElementEventStreamImpl only in dart2js to
    // avoid checked mode errors in dartium.
    return new _ElementEventStreamImpl<BeforeUnloadEvent>(e, _eventType, useCapture);
$else
    return new _ElementEventStreamImpl(e, _eventType, useCapture);
$endif
  }

  ElementStream<BeforeUnloadEvent> _forElementList(ElementList e,
      {bool useCapture: false}) {
$if DART2JS
    // Specify the generic type for _ElementEventStreamImpl only in dart2js to
    // avoid checked mode errors in dartium.
    return new _ElementListEventStreamImpl<BeforeUnloadEvent>(e, _eventType, useCapture);
$else
    return new _ElementListEventStreamImpl(e, _eventType, useCapture);
$endif
  }
}
