/*
 * Copyright 2011 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.touch.client;

import com.google.gwt.core.client.Duration;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
import com.google.gwt.dom.client.PartialSupport;
import com.google.gwt.dom.client.Touch;
import com.google.gwt.event.dom.client.TouchCancelEvent;
import com.google.gwt.event.dom.client.TouchCancelHandler;
import com.google.gwt.event.dom.client.TouchEndEvent;
import com.google.gwt.event.dom.client.TouchEndHandler;
import com.google.gwt.event.dom.client.TouchEvent;
import com.google.gwt.event.dom.client.TouchMoveEvent;
import com.google.gwt.event.dom.client.TouchMoveHandler;
import com.google.gwt.event.dom.client.TouchStartEvent;
import com.google.gwt.event.dom.client.TouchStartHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.touch.client.Momentum.State;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Event.NativePreviewEvent;
import com.google.gwt.user.client.Event.NativePreviewHandler;
import com.google.gwt.user.client.ui.HasScrolling;

import java.util.ArrayList;
import java.util.List;

/**
 * Adds touch based scrolling to a scroll panel.
 * 
 * <p>
 * Touch based scrolling is only supported on devices that support touch events
 * and do not implement native touch based scrolling.
 * </p>
 */
@PartialSupport
public class TouchScroller {

  /**
   * A point associated with a time.
   * 
   * Visible for testing.
   */
  static class TemporalPoint {
    private Point point;
    private double time;

    public TemporalPoint() {
    }

    /**
     * Construct a new {@link TemporalPoint} for the specified point and time.
     */
    public TemporalPoint(Point point, double time) {
      setTemporalPoint(point, time);
    }

    public Point getPoint() {
      return point;
    }

    public double getTime() {
      return time;
    }

    /**
     * Update the point and time.
     * 
     * @param point the new point
     * @param time the new time
     */
    public void setTemporalPoint(Point point, double time) {
      this.point = point;
      this.time = time;
    }
  }

  /**
   * The command used to apply momentum.
   */
  private class MomentumCommand implements RepeatingCommand {

    private final Duration duration = new Duration();
    private final Point initialPosition = getWidgetScrollPosition();
    private int lastElapsedMillis = 0;
    private State state;

    /**
     * Construct a {@link MomentumCommand}.
     * 
     * @param endVelocity the final velocity of the user drag
     */
    public MomentumCommand(Point endVelocity) {
      state = momentum.createState(initialPosition, endVelocity);
    }

    public boolean execute() {
      /*
       * Stop the command if another touch event starts or if momentum is
       * disabled.
       */
      if (this != momentumCommand) {
        return false;
      }

      // Get the current position from the momentum.
      int cumulativeElapsedMillis = duration.elapsedMillis();
      state.setElapsedMillis(cumulativeElapsedMillis - lastElapsedMillis);
      lastElapsedMillis = cumulativeElapsedMillis;
      state.setCumulativeElapsedMillis(cumulativeElapsedMillis);

      // Calculate the new state.
      boolean notDone = momentum.updateState(state);

      // Momementum is finished, so the user is free to click.
      if (!notDone) {
        setBustNextClick(false);
      }

      /*
       * Apply the new position. Even if there is no additional momentum, we
       * want to respect the end position that the momentum returns.
       */
      setWidgetScrollPosition(state.getPosition());
      return notDone;
    }
  }

  /**
   * The number of frames per second the animation should run at.
   */
  private static final double FRAMES_PER_SECOND = 60;

  /**
   * The number of ms to wait during a drag before updating the reported start
   * position of the drag.
   */
  private static final double MAX_TRACKING_TIME = 200;

  /**
   * The number of ms to wait before putting a position on deck.
   */
  private static final double MAX_TRACKING_TIME_ON_DECK = MAX_TRACKING_TIME / 2;

  /**
   * Minimum movement of touch required to be considered a drag.
   */
  private static final double MIN_TRACKING_FOR_DRAG = 5;

  /**
   * The number of milliseconds per animation frame.
   */
  private static final int MS_PER_FRAME = (int) (1000 / FRAMES_PER_SECOND);

  /**
   * A cached boolean indicating whether or not touch scrolling is supported.
   * Set to a non-null value the first time {@link #isSupported()} is called.
   */
  private static Boolean isSupported;

  /**
   * Return a new {@link TouchScroller}.
   * 
   * @return a new {@link TouchScroller} if supported, and null otherwise
   */
  public static TouchScroller createIfSupported() {
    return isSupported() ? new TouchScroller() : null;
  }

  /**
   * Return a new {@link TouchScroller} that augments the specified scrollable
   * widget if supported, and null otherwise.
   * 
   * @param widget the scrollable widget
   * @return a new {@link TouchScroller} if supported, and null otherwise
   */
  public static TouchScroller createIfSupported(HasScrolling widget) {
    TouchScroller scroller = createIfSupported();
    if (scroller != null) {
      scroller.setTargetWidget(widget);
    }
    return scroller;
  }

  /**
   * Runtime check for whether touch scrolling is supported in this browser.
   * Returns true if touch events are supported but touch based scrolling is not
   * natively supported.
   * 
   * @return true if touch scrolling is supported, false if not
   */
  public static boolean isSupported() {
    if (isSupported == null) {
      /*
       * Android 3.0 devices support touch scrolling natively.
       * 
       * TODO(jlabanca): Find a more reliable way to detect if native touch
       * scrolling is supported.
       */
      isSupported = TouchEvent.isSupported() && !isAndroid3();
    }
    return isSupported;
  }

  /**
   * Check if the user agent is android 3.0 or greater.
   * 
   * @return true if android 3.0+
   * 
   */
  private static native boolean isAndroid3() /*-{
    var ua = navigator.userAgent.toLowerCase();
    return /android ([3-9]+)\.([0-9]+)/.exec(ua) != null;
  }-*/;

  /**
   * The registration for the preview handler used to bust click events.
   */
  private HandlerRegistration bustClickHandler;

  /**
   * A boolean indicating that we are in a drag sequence. Dragging occurs after
   * the user moves beyond a threshold distance.
   */
  private boolean dragging;

  /**
   * Registrations for the handlers added to the widget.
   */
  private final List<HandlerRegistration> handlerRegs = new ArrayList<HandlerRegistration>();

  /**
   * The last (most recent) touch position. We need to keep track of this when
   * we handle touch move events because the Touch is already destroyed before
   * the touch end event fires.
   */
  private final TemporalPoint lastTouchPosition = new TemporalPoint();

  /**
   * The momentum that determines how the widget scrolls after the user
   * completes a gesture. Can be null if momentum is not supported.
   */
  private Momentum momentum;

  /**
   * The repeating command used to continue momentum after the gesture ends. The
   * command is instantiated after the user finishes a drag sequence. A non null
   * value indicates that momentum is occurring.
   */
  private RepeatingCommand momentumCommand;

  /**
   * The coordinate of the most recent relevant touch event. For most drag
   * sequences this will be the same as the startCoordinate. If the touch
   * gesture changes direction significantly or pauses for a while this
   * coordinate will be updated to the coordinate of the on deck touchmove
   * event.
   */
  private final TemporalPoint recentTouchPosition = new TemporalPoint();

  /**
   * If the gesture takes too long, we update the recentTouchPosition to the
   * position on deck, which occurred halfway through the max tracking time. We
   * do this so that we don't base the velocity on two touch events that
   * occurred very close to each other at the end of a long gesture.
   */
  private TemporalPoint recentTouchPositionOnDeck;

  /**
   * The position of the scrollable when the first touch occured.
   */
  private Point startScrollPosition;

  /**
   * The position of the first touch.
   */
  private Point startTouchPosition;

  /**
   * A boolean indicating that we are in a touch sequence.
   */
  private boolean touching;

  /**
   * The widget being augmented.
   */
  private HasScrolling widget;

  /**
   * Construct a new {@link TouchScroller}. This constructor should be called
   * using the static method {@link #createIfSupported()}.
   * 
   * @param widget the widget to augment
   * @see #createIfSupported()
   */
  protected TouchScroller() {
    setMomentum(new DefaultMomentum());
  }

  /**
   * Get the {@link Momentum} that controls scrolling after the user completes a
   * gesture.
   * 
   * @return the scrolling {@link Momentum}, or null if disabled
   */
  public Momentum getMomentum() {
    return momentum;
  }

  /**
   * Get the target {@link HasScrolling} widget that this scroller affects.
   * 
   * @return the target widget
   */
  public HasScrolling getTargetWidget() {
    return widget;
  }

  /**
   * Set the {@link Momentum} that controls scrolling after the user completes a
   * gesture.
   * 
   * @param momentum the scrolling {@link Momentum}, or null to disable
   */
  public void setMomentum(Momentum momentum) {
    this.momentum = momentum;
    if (momentum == null) {
      // Cancel the current momentum.
      momentumCommand = null;
    }
  }

  /**
   * Set the target {@link HasScrolling} widget that this scroller affects.
   * 
   * @param widget the target widget, or null to disbale
   */
  public void setTargetWidget(HasScrolling widget) {
    if (this.widget == widget) {
      return;
    }

    // Cancel drag and momentum.
    cancelAll();
    setBustNextClick(false);

    // Release the old widget.
    if (this.widget != null) {
      for (HandlerRegistration reg : handlerRegs) {
        reg.removeHandler();
      }
      handlerRegs.clear();
    }

    // Attach to the new widget.
    this.widget = widget;
    if (widget != null) {
      // Add touch start handler.
      handlerRegs.add(widget.asWidget().addDomHandler(new TouchStartHandler() {
        public void onTouchStart(TouchStartEvent event) {
          TouchScroller.this.onTouchStart(event);
        }
      }, TouchStartEvent.getType()));

      // Add touch move handler.
      handlerRegs.add(widget.asWidget().addDomHandler(new TouchMoveHandler() {
        public void onTouchMove(TouchMoveEvent event) {
          TouchScroller.this.onTouchMove(event);
        }
      }, TouchMoveEvent.getType()));

      // Add touch end handler.
      handlerRegs.add(widget.asWidget().addDomHandler(new TouchEndHandler() {
        public void onTouchEnd(TouchEndEvent event) {
          TouchScroller.this.onTouchEnd(event);
        }
      }, TouchEndEvent.getType()));

      // Add touch cancel handler.
      handlerRegs.add(widget.asWidget().addDomHandler(new TouchCancelHandler() {
        public void onTouchCancel(TouchCancelEvent event) {
          TouchScroller.this.onTouchCancel(event);
        }
      }, TouchCancelEvent.getType()));
    }
  }

  /**
   * Get touch from event.
   * 
   * @param event the event
   * @return the touch object
   */
  protected Touch getTouchFromEvent(TouchEvent<?> event) {
    JsArray<Touch> touches = event.getTouches();
    return (touches.length() > 0) ? touches.get(0) : null;
  }

  /**
   * Called when the object's drag sequence is complete.
   * 
   * @param event the touch event
   */
  protected void onDragEnd(TouchEvent<?> event) {
    // There is no momentum or it isn't supported.
    if (momentum == null) {
      return;
    }

    // Schedule the momentum.
    Point endVelocity = calculateEndVelocity(recentTouchPosition, lastTouchPosition);
    if (endVelocity != null) {
      momentumCommand = new MomentumCommand(endVelocity);
      Scheduler.get().scheduleFixedDelay(momentumCommand, MS_PER_FRAME);
    }
  }

  /**
   * Called when the object has been dragged to a new position.
   * 
   * @param event the touch event
   */
  protected void onDragMove(TouchEvent<?> event) {
    /*
     * Scroll to the new position. Touch scrolling moves in the same direction
     * as the finger dragging, whereas scrolling is inverted with traditional
     * scrollbars.
     */
    Point diff = startTouchPosition.minus(lastTouchPosition.getPoint());
    Point curScrollPosition = startScrollPosition.plus(diff);
    setWidgetScrollPosition(curScrollPosition);
  }

  /**
   * Called when the object has started dragging.
   * 
   * @param event the touch event
   */
  protected void onDragStart(TouchEvent<?> event) {
  }

  /**
   * Called when the user cancels a touch. This can happen if the user touches
   * the screen with too many fingers.
   * 
   * @param event the touch event
   */
  protected void onTouchCancel(TouchEvent<?> event) {
    onTouchEnd(event);
  }

  /**
   * Called when the user releases a touch.
   * 
   * @param event the touch event
   */
  protected void onTouchEnd(TouchEvent<?> event) {
    // Ignore the touch if we didn't catch a touch start event.
    if (!touching) {
      return;
    }
    touching = false;

    // Stop dragging.
    if (dragging) {
      dragging = false;
      onDragEnd(event);
    }
  }

  /**
   * Called when the user moves a touch.
   * 
   * @param event the touch event
   */
  protected void onTouchMove(TouchEvent<?> event) {
    // Ignore the touch if we never caught a touch start event.
    if (!touching) {
      return;
    }

    // Prevent native scrolling.
    event.preventDefault();

    // Check if we should start dragging.
    Touch touch = getTouchFromEvent(event);
    Point touchPoint = new Point(touch.getPageX(), touch.getPageY());
    double touchTime = Duration.currentTimeMillis();
    lastTouchPosition.setTemporalPoint(touchPoint, touchTime);
    if (!dragging) {
      Point diff = touchPoint.minus(startTouchPosition);
      double absDiffX = Math.abs(diff.getX());
      double absDiffY = Math.abs(diff.getY());
      if (absDiffX > MIN_TRACKING_FOR_DRAG || absDiffY > MIN_TRACKING_FOR_DRAG) {
        // Start dragging.
        dragging = true;
        onDragStart(event);
      }
    }

    if (dragging) {
      // Continue dragging.
      onDragMove(event);

      /*
       * Update the recent position. This happens when they are dragging slowly.
       * If they are dragging slowly then we should reset the start time and
       * position to where they are now. This will be important during the drag
       * end when we report to the draggable delegate what kind of drag just
       * happened.
       */
      double trackingTime = touchTime - recentTouchPosition.getTime();
      if (trackingTime > MAX_TRACKING_TIME && recentTouchPositionOnDeck != null) {
        // See comment below.
        recentTouchPosition.setTemporalPoint(recentTouchPositionOnDeck.getPoint(),
            recentTouchPositionOnDeck.getTime());
        recentTouchPositionOnDeck = null;
      } else if (trackingTime > MAX_TRACKING_TIME_ON_DECK && recentTouchPositionOnDeck == null) {
        /*
         * When we are halfway to the max tracking time, put the current touch
         * on deck. When we switch the recent touch position, we use the on deck
         * position. That prevents us from calculating the velocity from two
         * points that are too close in time (or the same time).
         */
        recentTouchPositionOnDeck = new TemporalPoint(touchPoint, touchTime);
      }
    }
  }

  /**
   * Called when the user starts a touch.
   * 
   * @param event the touch event
   */
  protected void onTouchStart(TouchEvent<?> event) {
    // Ignore the touch if there is already a touch happening.
    if (touching) {
      return;
    }

    /*
     * If the user touches the screen while momentum is scrolling, bust the next
     * click event. They probably want to pause the momentum, not click an item.
     */
    setBustNextClick(isMomentumActive());

    cancelAll();
    touching = true;

    // Record the starting touch position.
    Touch touch = getTouchFromEvent(event);
    startTouchPosition = new Point(touch.getPageX(), touch.getPageY());
    double startTouchTime = Duration.currentTimeMillis();
    recentTouchPosition.setTemporalPoint(startTouchPosition, startTouchTime);
    lastTouchPosition.setTemporalPoint(startTouchPosition, startTouchTime);
    recentTouchPositionOnDeck = null;

    // Record the starting scroll position.
    startScrollPosition = getWidgetScrollPosition();
  }

  /**
   * Calculate the end velocity. Visible for testing.
   * 
   * @param from the starting point
   * @param to the ending point
   * @return the end velocity, or null if it cannot be calculated
   */
  Point calculateEndVelocity(TemporalPoint from, TemporalPoint to) {
    /*
     * Calculate the time since the recent touch. The time can be zero if the
     * user pauses for too long, which updates the recentTouchPosition, then
     * lets go without moving again.
     */
    double time = to.getTime() - from.getTime();
    if (time <= 0) {
      return null;
    }

    /*
     * Calculate the end velocities. The velocity is inverted from the direction
     * of the gesture.
     */
    Point dist = from.getPoint().minus(to.getPoint());
    return new Point(dist.getX() / time, dist.getY() / time);
  }

  /**
   * Visible for testing.
   */
  TemporalPoint getLastTouchPosition() {
    return lastTouchPosition;
  }

  /**
   * Visible for testing.
   */
  TemporalPoint getRecentTouchPosition() {
    return recentTouchPosition;
  }

  /**
   * Visible for testing.
   */
  boolean isDragging() {
    return dragging;
  }

  /**
   * Check if momentum is currently active. Visible for testing.
   * 
   * @return true if active, false if not
   */
  boolean isMomentumActive() {
    return (momentumCommand != null);
  }

  /**
   * Visible for testing.
   */
  boolean isTouching() {
    return touching;
  }

  /**
   * Cancel all existing touch, drag, and momentum.
   */
  private void cancelAll() {
    touching = false;
    dragging = false;
    momentumCommand = null;
  }

  /**
   * Get the scroll position of the widget.
   * 
   * @param position the current scroll position
   */
  private Point getWidgetScrollPosition() {
    return new Point(widget.getHorizontalScrollPosition(), widget.getVerticalScrollPosition());
  }

  /**
   * Set whether or not we should bust the next click.
   * 
   * @param doBust true to bust the next click, false not to
   */
  private void setBustNextClick(boolean doBust) {
    if (doBust && bustClickHandler == null) {
      bustClickHandler = Event.addNativePreviewHandler(new NativePreviewHandler() {
        public void onPreviewNativeEvent(NativePreviewEvent event) {
          if (Event.ONCLICK == event.getTypeInt()) {
            event.getNativeEvent().stopPropagation();
            event.getNativeEvent().preventDefault();
            setBustNextClick(false);
          }
        };
      });
    } else if (!doBust && bustClickHandler != null) {
      bustClickHandler.removeHandler();
      bustClickHandler = null;
    }
  }

  /**
   * Set the scroll position of the widget.
   * 
   * @param position the new position
   */
  private void setWidgetScrollPosition(Point position) {
    widget.setHorizontalScrollPosition((int) position.getX());
    widget.setVerticalScrollPosition((int) position.getY());
  }
}
