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

part of touch;

/**
 * Implementation of a custom scrolling behavior.
 * This behavior overrides native scrolling for an area. This area can be a
 * single defined part of a page, the entire page, or several different parts
 * of a page.
 *
 * To use this scrolling behavior you need to define a frame and the content.
 * The frame defines the area that the content will scroll within. The frame and
 * content must both be HTML Elements, with the content being a direct child of
 * the frame. Usually the frame is smaller in size than the content. This is
 * not necessary though, if the content is smaller then bouncing will occur to
 * provide feedback that you are past the scrollable area.
 *
 * The scrolling behavior works using the webkit translate3d transformation,
 * which means browsers that do not have hardware accelerated transformations
 * will not perform as well using this. Simple scrolling should be fine even
 * without hardware acceleration, but animating momentum and deceleration is
 * unacceptably slow without it. There is also the option to use relative
 * positioning (setting the left and top styles).
 *
 * For this to work properly you need to set -webkit-text-size-adjust to 'none'
 * on an ancestor element of the frame, or on the frame itself. If you forget
 * this you may see the text content of the scrollable area changing size as it
 * moves.
 *
 * The behavior is intended to support vertical and horizontal scrolling, and
 * scrolling with momentum when a touch gesture flicks with enough velocity.
 */
typedef void Callback();

// Helper method to await the completion of 2 futures.
void joinFutures(List<Future> futures, Callback callback) {
  int count = 0;
  int len = futures.length;
  void helper(value) {
    count++;
    if (count == len) {
      callback();
    }
  }

  for (Future p in futures) {
    p.then(helper);
  }
}

class Scroller implements Draggable, MomentumDelegate {
  /** Pixels to move each time an arrow key is pressed. */
  static const ARROW_KEY_DELTA = 30;
  static const SCROLL_WHEEL_VELOCITY = 0.01;
  static const FAST_SNAP_DECELERATION_FACTOR = 0.84;
  static const PAGE_KEY_SCROLL_FRACTION = .85;

  // TODO(jacobr): remove this static variable.
  static bool _dragInProgress = false;

  /** The node that will actually scroll. */
  Element _element;

  /**
   * Frame is the node that will serve as the container for the scrolling
   * content.
   */
  Element _frame;

  /** Touch manager to track the events on the scrollable area. */
  TouchHandler _touchHandler;

  Momentum _momentum;

  StreamController<Event> _onScrollerStart;
  Stream<Event> _onScrollerStartStream;
  StreamController<Event> _onScrollerEnd;
  Stream<Event> _onScrollerEndStream;
  StreamController<Event> _onScrollerDragEnd;
  Stream<Event> _onScrollerDragEndStream;
  StreamController<Event> _onContentMoved;
  Stream<Event> _onContentMovedStream;
  StreamController<Event> _onDecelStart;
  Stream<Event> _onDecelStartStream;

  /** Set if vertical scrolling should be enabled. */
  bool verticalEnabled;

  /** Set if horizontal scrolling should be enabled. */
  bool horizontalEnabled;

  /**
   * Set if momentum should be enabled.
   */
  bool _momentumEnabled;

  /** Set which type of scrolling translation technique should be used. */
  int _scrollTechnique;

  /**
   * The maximum coordinate that the left upper corner of the content can scroll
   * to.
   */
  Coordinate _maxPoint;

  /**
   * An offset to subtract from the maximum coordinate that the left upper
   * corner of the content can scroll to.
   */
  Coordinate _maxOffset;

  /**
   * An offset to add to the minimum coordinate that the left upper corner of
   * the content can scroll to.
   */
  Coordinate _minOffset;

  /** Initialize the current content offset. */
  Coordinate _contentOffset;

  // TODO(jacobr): the function type is
  // [:Function(Element, num, num)->void:].
  /**
   * The function to use that will actually translate the scrollable node.
   */
  Function _setOffsetFunction;
  /**
   * Function that returns the content size that can be specified instead of
   * querying the DOM.
   */
  Function _lookupContentSizeDelegate;

  Size _scrollSize;
  Size _contentSize;
  Coordinate _minPoint;
  bool _isStopping = false;
  Coordinate _contentStartOffset;
  bool _started = false;
  bool _activeGesture = false;
  ScrollWatcher _scrollWatcher;

  Scroller(Element scrollableElem,
      [this.verticalEnabled = false,
      this.horizontalEnabled = false,
      momentumEnabled = true,
      lookupContentSizeDelegate = null,
      num defaultDecelerationFactor = 1,
      int scrollTechnique = null,
      bool capture = false])
      : _momentumEnabled = momentumEnabled,
        _lookupContentSizeDelegate = lookupContentSizeDelegate,
        _element = scrollableElem,
        _frame = scrollableElem.parent,
        _scrollTechnique = scrollTechnique != null
            ? scrollTechnique
            : ScrollerScrollTechnique.TRANSFORM_3D,
        _minPoint = new Coordinate(0, 0),
        _maxPoint = new Coordinate(0, 0),
        _maxOffset = new Coordinate(0, 0),
        _minOffset = new Coordinate(0, 0),
        _contentOffset = new Coordinate(0, 0) {
    _touchHandler = new TouchHandler(this, scrollableElem.parent);
    _momentum = new Momentum(this, defaultDecelerationFactor);

    Element parentElem = scrollableElem.parent;
    assert(parentElem != null);
    _setOffsetFunction = _getOffsetFunction(_scrollTechnique);
    _touchHandler.setDraggable(this);
    _touchHandler.enable(capture);

    _frame.onMouseWheel.listen((e) {
      if (e.deltaY != 0 && verticalEnabled ||
          e.deltaX != 0 && horizontalEnabled) {
        num x = horizontalEnabled ? e.deltaX : 0;
        num y = verticalEnabled ? e.deltaY : 0;
        throwDelta(x, y, FAST_SNAP_DECELERATION_FACTOR);
        e.preventDefault();
      }
    });

    _frame.onKeyDown.listen((KeyboardEvent e) {
      bool handled = false;
      // We ignore key events where further scrolling in that direction
      // would have no impact which matches default browser behavior with
      // nested scrollable areas.

      switch (e.keyCode) {
        case 33: // page-up
          throwDelta(0, _scrollSize.height * PAGE_KEY_SCROLL_FRACTION);
          handled = true;
          break;
        case 34: // page-down
          throwDelta(0, -_scrollSize.height * PAGE_KEY_SCROLL_FRACTION);
          handled = true;
          break;
        case 35: // End
          throwTo(_maxPoint.x, _minPoint.y, FAST_SNAP_DECELERATION_FACTOR);
          handled = true;
          break;
        case 36: // Home
          throwTo(_maxPoint.x, _maxPoint.y, FAST_SNAP_DECELERATION_FACTOR);
          handled = true;
          break;
/* TODO(jacobr): enable arrow keys when the don't conflict with other
   application keyboard shortcuts.
          case 38: // up
            handled = throwDelta(
                0,
                ARROW_KEY_DELTA,
                FAST_SNAP_DECELERATION_FACTOR);
            break;
          case 40: // down
            handled = throwDelta(
                0, -ARROW_KEY_DELTA,
                FAST_SNAP_DECELERATION_FACTOR);
            break;
          case 37: // left
            handled = throwDelta(
                ARROW_KEY_DELTA, 0,
                FAST_SNAP_DECELERATION_FACTOR);
            break;
          case 39: // right
            handled = throwDelta(
                -ARROW_KEY_DELTA,
                0,
                FAST_SNAP_DECELERATION_FACTOR);
            break;
            */
      }
      if (handled) {
        e.preventDefault();
      }
    });
    // The scrollable element must be relatively positioned.
    // TODO(jacobr): this assert fires asynchronously which could be confusing.
    if (_scrollTechnique == ScrollerScrollTechnique.RELATIVE_POSITIONING) {
      assert(_element.getComputedStyle().position != "static");
    }

    _initLayer();
  }

  Stream<Event> get onScrollerStart {
    if (_onScrollerStart == null) {
      _onScrollerStart = new StreamController<Event>.broadcast(sync: true);
      _onScrollerStartStream = _onScrollerStart.stream;
    }
    return _onScrollerStartStream;
  }

  Stream<Event> get onScrollerEnd {
    if (_onScrollerEnd == null) {
      _onScrollerEnd = new StreamController<Event>.broadcast(sync: true);
      _onScrollerEndStream = _onScrollerEnd.stream;
    }
    return _onScrollerEndStream;
  }

  Stream<Event> get onScrollerDragEnd {
    if (_onScrollerDragEnd == null) {
      _onScrollerDragEnd = new StreamController<Event>.broadcast(sync: true);
      _onScrollerDragEndStream = _onScrollerDragEnd.stream;
    }
    return _onScrollerDragEndStream;
  }

  Stream<Event> get onContentMoved {
    if (_onContentMoved == null) {
      _onContentMoved = new StreamController<Event>.broadcast(sync: true);
      _onContentMovedStream = _onContentMoved.stream;
    }
    return _onContentMovedStream;
  }

  Stream<Event> get onDecelStart {
    if (_onDecelStart == null) {
      _onDecelStart = new StreamController<Event>.broadcast(sync: true);
      _onDecelStartStream = _onDecelStart.stream;
    }
    return _onDecelStartStream;
  }

  /**
   * Add a scroll listener. This allows other classes to subscribe to scroll
   * notifications from this scroller.
   */
  void addScrollListener(ScrollListener listener) {
    if (_scrollWatcher == null) {
      _scrollWatcher = new ScrollWatcher(this);
      _scrollWatcher.initialize();
    }
    _scrollWatcher.addListener(listener);
  }

  /**
   * Adjust the new calculated scroll position based on the minimum allowed
   * position and returns the adjusted scroll value.
   */
  num _adjustValue(num newPosition, num minPosition, num maxPosition) {
    assert(minPosition <= maxPosition);

    if (newPosition < minPosition) {
      newPosition -= (newPosition - minPosition) / 2;
    } else {
      if (newPosition > maxPosition) {
        newPosition -= (newPosition - maxPosition) / 2;
      }
    }
    return newPosition;
  }

  /**
   * Coordinate we would end up at if we did nothing.
   */
  Coordinate get currentTarget {
    Coordinate end = _momentum.destination;
    if (end == null) {
      end = _contentOffset;
    }
    return end;
  }

  Coordinate get contentOffset => _contentOffset;

  /**
   * Animate the position of the scroller to the specified [x], [y] coordinates
   * by applying the throw gesture with the correct velocity to end at that
   * location.
   */
  void throwTo(num x, num y, [num decelerationFactor = null]) {
    reconfigure(() {
      final snappedTarget = _snapToBounds(x, y);
      // If a deceleration factor is not specified, use the existing
      // deceleration factor specified by the momentum simulator.
      if (decelerationFactor == null) {
        decelerationFactor = _momentum.decelerationFactor;
      }

      if (snappedTarget != currentTarget) {
        _momentum.abort();

        _startDeceleration(
            _momentum.calculateVelocity(
                _contentOffset, snappedTarget, decelerationFactor),
            decelerationFactor);
        if (_onDecelStart != null) {
          _onDecelStart.add(new Event(ScrollerEventType.DECEL_START));
        }
      }
    });
  }

  void throwDelta(num deltaX, num deltaY, [num decelerationFactor = null]) {
    Coordinate start = _contentOffset;
    Coordinate end = currentTarget;
    int x = end.x.toInt();
    int y = end.y.toInt();
    // If we are throwing in the opposite direction of the existing momentum,
    // cancel the current momentum.
    if (deltaX != 0 && deltaX.isNegative != (end.x - start.x).isNegative) {
      x = start.x;
    }
    if (deltaY != 0 && deltaY.isNegative != (end.y - start.y).isNegative) {
      y = start.y;
    }
    x += deltaX.toInt();
    y += deltaY.toInt();
    throwTo(x, y, decelerationFactor);
  }

  void setPosition(num x, num y) {
    _momentum.abort();
    _contentOffset.x = x;
    _contentOffset.y = y;
    _snapContentOffsetToBounds();
    _setContentOffset(_contentOffset.x, _contentOffset.y);
  }

  /**
   * Adjusted content size is a size with the combined largest height and width
   * of both the content and the frame.
   */
  Size _getAdjustedContentSize() {
    return new Size(Math.max(_scrollSize.width, _contentSize.width),
        Math.max(_scrollSize.height, _contentSize.height));
  }

  // TODO(jmesserly): these should be properties instead of get* methods
  num getDefaultVerticalOffset() => _maxPoint.y;
  Element getElement() => _element;
  Element getFrame() => _frame;
  num getHorizontalOffset() => _contentOffset.x;

  /**
   * [x] Value to use as reference for percent measurement. If
   *      none is provided then the content's current x offset will be used.
   * Returns the percent of the page scrolled horizontally.
   */
  num getHorizontalScrollPercent([num x = null]) {
    x = x != null ? x : _contentOffset.x;
    return (x - _minPoint.x) / (_maxPoint.x - _minPoint.x);
  }

  num getMaxPointY() => _maxPoint.y;
  num getMinPointY() => _minPoint.y;
  Momentum get momentum => _momentum;

  /**
   * Provide access to the touch handler that the scroller created to manage
   * touch events.
   */
  TouchHandler getTouchHandler() => _touchHandler;
  num getVerticalOffset() => _contentOffset.y;

  /**
   * [y] value is used as reference for percent measurement. If
   * none is provided then the content's current y offset will be used.
   */
  num getVerticalScrollPercent([num y = null]) {
    y = y != null ? y : _contentOffset.y;
    return (y - _minPoint.y) / Math.max(1, _maxPoint.y - _minPoint.y);
  }

  /**
   * Initialize the dom elements necessary for the scrolling to work.
   */
  void _initLayer() {
    // The scrollable node provided to Scroller must be a direct child
    // of the scrollable frame.
    // TODO(jacobr): Figure out why this is failing on dartium.
    // assert(_element.parent == _frame);
    _setContentOffset(_maxPoint.x, _maxPoint.y);
  }

  void onDecelerate(num x, num y) {
    _setContentOffset(x, y);
  }

  void onDecelerationEnd() {
    if (_onScrollerEnd != null) {
      _onScrollerEnd.add(new Event(ScrollerEventType.SCROLLER_END));
    }
    _started = false;
  }

  void onDragEnd() {
    _dragInProgress = false;

    bool decelerating = false;
    if (_activeGesture) {
      if (_momentumEnabled) {
        decelerating = _startDeceleration(_touchHandler.getEndVelocity());
      }
    }

    if (_onScrollerDragEnd != null) {
      _onScrollerDragEnd.add(new Event(ScrollerEventType.DRAG_END));
    }

    if (!decelerating) {
      _snapContentOffsetToBounds();
      if (_onScrollerEnd != null) {
        _onScrollerEnd.add(new Event(ScrollerEventType.SCROLLER_END));
      }
      _started = false;
    } else {
      if (_onDecelStart != null) {
        _onDecelStart.add(new Event(ScrollerEventType.DECEL_START));
      }
    }
    _activeGesture = false;
  }

  void onDragMove() {
    if (_isStopping || (!_activeGesture && _dragInProgress)) {
      return;
    }

    assert(_contentStartOffset != null); // Content start not set
    Coordinate contentStart = _contentStartOffset;
    num newX = contentStart.x + _touchHandler.getDragDeltaX();
    num newY = contentStart.y + _touchHandler.getDragDeltaY();
    newY = _shouldScrollVertically()
        ? _adjustValue(newY, _minPoint.y, _maxPoint.y)
        : 0;
    newX = _shouldScrollHorizontally()
        ? _adjustValue(newX, _minPoint.x, _maxPoint.x)
        : 0;
    if (!_activeGesture) {
      _activeGesture = true;
      _dragInProgress = true;
    }
    if (!_started) {
      _started = true;
      if (_onScrollerStart != null) {
        _onScrollerStart.add(new Event(ScrollerEventType.SCROLLER_START));
      }
    }
    _setContentOffset(newX, newY);
  }

  bool onDragStart(TouchEvent e) {
    if (e.touches.length > 1) {
      return false;
    }
    bool shouldHorizontal = _shouldScrollHorizontally();
    bool shouldVertical = _shouldScrollVertically();
    bool verticalish = _touchHandler.getDragDeltaY().abs() >
        _touchHandler.getDragDeltaX().abs();
    return !!(shouldVertical || shouldHorizontal && !verticalish);
  }

  void onTouchEnd() {}

  /**
   * Prepare the scrollable area for possible movement.
   */
  bool onTouchStart(TouchEvent e) {
    reconfigure(() {
      final touch = e.touches[0];
      if (_momentum.decelerating) {
        e.preventDefault();
        e.stopPropagation();
        stop();
      }
      _contentStartOffset = _contentOffset.clone();
      _snapContentOffsetToBounds();
    });
    return true;
  }

  /**
   * Recalculate dimensions of the frame and the content. Adjust the minPoint
   * and maxPoint allowed for scrolling and scroll to a valid position. Call
   * this method if you know the frame or content has been updated. Called
   * internally on every touchstart event the frame receives.
   */
  void reconfigure(Callback callback) {
    _resize(() {
      _snapContentOffsetToBounds();
      callback();
    });
  }

  void reset() {
    stop();
    _touchHandler.reset();
    _maxOffset.x = 0;
    _maxOffset.y = 0;
    _minOffset.x = 0;
    _minOffset.y = 0;
    reconfigure(() => _setContentOffset(_maxPoint.x, _maxPoint.y));
  }

  /**
   * Recalculate dimensions of the frame and the content. Adjust the minPoint
   * and maxPoint allowed for scrolling.
   */
  void _resize(Callback callback) {
    scheduleMicrotask(() {
      if (_lookupContentSizeDelegate != null) {
        _contentSize = _lookupContentSizeDelegate();
      } else {
        _contentSize = new Size(_element.scrollWidth, _element.scrollHeight);
      }

      _scrollSize = new Size(_frame.offset.width, _frame.offset.height);
      Size adjusted = _getAdjustedContentSize();
      _maxPoint = new Coordinate(-_maxOffset.x, -_maxOffset.y);
      _minPoint = new Coordinate(
          Math.min(
              _scrollSize.width - adjusted.width + _minOffset.x, _maxPoint.x),
          Math.min(_scrollSize.height - adjusted.height + _minOffset.y,
              _maxPoint.y));
      callback();
    });
  }

  Coordinate _snapToBounds(num x, num y) {
    num clampX = GoogleMath.clamp(_minPoint.x, x, _maxPoint.x);
    num clampY = GoogleMath.clamp(_minPoint.y, y, _maxPoint.y);
    return new Coordinate(clampX, clampY);
  }

  /**
   * Translate the content to a new position specified in px.
   */
  void _setContentOffset(num x, num y) {
    _contentOffset.x = x;
    _contentOffset.y = y;
    _setOffsetFunction(_element, x, y);
    if (_onContentMoved != null) {
      _onContentMoved.add(new Event(ScrollerEventType.CONTENT_MOVED));
    }
  }

  /**
   * Enable or disable momentum.
   */
  void setMomentum(bool enable) {
    _momentumEnabled = enable;
  }

  /**
   * Sets the vertical scrolled offset of the element where [y] is the amount
   * of vertical space to be scrolled, in pixels.
   */
  void setVerticalOffset(num y) {
    _setContentOffset(_contentOffset.x, y);
  }

  /**
   * Whether the scrollable area should scroll horizontally. Only
   * returns true if the client has enabled horizontal scrolling, and the
   * content is wider than the frame.
   */
  bool _shouldScrollHorizontally() {
    return horizontalEnabled && _scrollSize.width < _contentSize.width;
  }

  /**
   * Whether the scrollable area should scroll vertically. Only
   * returns true if the client has enabled vertical scrolling.
   * Vertical bouncing will occur even if frame is taller than content, because
   * this is what iPhone web apps tend to do. If this is not the desired
   * behavior, either disable vertical scrolling for this scroller or add a
   * 'bouncing' parameter to this interface.
   */
  bool _shouldScrollVertically() {
    return verticalEnabled;
  }

  /**
   * In the event that the content is currently beyond the bounds of
   * the frame, snap it back in to place.
   */
  void _snapContentOffsetToBounds() {
    num clampX = GoogleMath.clamp(_minPoint.x, _contentOffset.x, _maxPoint.x);
    num clampY = GoogleMath.clamp(_minPoint.y, _contentOffset.y, _maxPoint.y);
    if (_contentOffset.x != clampX || _contentOffset.y != clampY) {
      _setContentOffset(clampX, clampY);
    }
  }

  /**
   * Initiate the deceleration behavior given a flick [velocity].
   * Returns true if deceleration has been initiated.
   */
  bool _startDeceleration(Coordinate velocity,
      [num decelerationFactor = null]) {
    if (!_shouldScrollHorizontally()) {
      velocity.x = 0;
    }
    if (!_shouldScrollVertically()) {
      velocity.y = 0;
    }
    assert(_minPoint != null); // Min point is not set
    assert(_maxPoint != null); // Max point is not set
    return _momentum.start(
        velocity, _minPoint, _maxPoint, _contentOffset, decelerationFactor);
  }

  Coordinate stop() {
    return _momentum.stop();
  }

  /**
   * Stop the deceleration of the scrollable content given a new position in px.
   */
  void _stopDecelerating(num x, num y) {
    _momentum.stop();
    _setContentOffset(x, y);
  }

  static Function _getOffsetFunction(int scrollTechnique) {
    return scrollTechnique == ScrollerScrollTechnique.TRANSFORM_3D
        ? (el, x, y) {
            FxUtil.setTranslate(el, x, y, 0);
          }
        : (el, x, y) {
            FxUtil.setLeftAndTop(el, x, y);
          };
  }
}

// TODO(jacobr): cleanup this class of enum constants.
class ScrollerEventType {
  static const SCROLLER_START = "scroller:scroll_start";
  static const SCROLLER_END = "scroller:scroll_end";
  static const DRAG_END = "scroller:drag_end";
  static const CONTENT_MOVED = "scroller:content_moved";
  static const DECEL_START = "scroller:decel_start";
}

class ScrollerScrollTechnique {
  static const TRANSFORM_3D = 1;
  static const RELATIVE_POSITIONING = 2;
}
