/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * 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.android.internal.policy;

import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
import android.util.Size;
import android.view.Gravity;
import android.view.ViewConfiguration;
import android.widget.Scroller;

import java.io.PrintWriter;
import java.util.ArrayList;

/**
 * Calculates the snap targets and the snap position for the PIP given a position and a velocity.
 * All bounds are relative to the display top/left.
 */
public class PipSnapAlgorithm {

    // The below SNAP_MODE_* constants correspond to the config resource value
    // config_pictureInPictureSnapMode and should not be changed independently.
    // Allows snapping to the four corners
    private static final int SNAP_MODE_CORNERS_ONLY = 0;
    // Allows snapping to the four corners and the mid-points on the long edge in each orientation
    private static final int SNAP_MODE_CORNERS_AND_SIDES = 1;
    // Allows snapping to anywhere along the edge of the screen
    private static final int SNAP_MODE_EDGE = 2;
    // Allows snapping anywhere along the edge of the screen and magnets towards corners
    private static final int SNAP_MODE_EDGE_MAGNET_CORNERS = 3;
    // Allows snapping on the long edge in each orientation and magnets towards corners
    private static final int SNAP_MODE_LONG_EDGE_MAGNET_CORNERS = 4;

    // Threshold to magnet to a corner
    private static final float CORNER_MAGNET_THRESHOLD = 0.3f;

    private final Context mContext;

    private final ArrayList<Integer> mSnapGravities = new ArrayList<>();
    private final int mDefaultSnapMode = SNAP_MODE_EDGE_MAGNET_CORNERS;
    private int mSnapMode = mDefaultSnapMode;

    private final float mDefaultSizePercent;
    private final float mMinAspectRatioForMinSize;
    private final float mMaxAspectRatioForMinSize;
    private final int mFlingDeceleration;

    private int mOrientation = Configuration.ORIENTATION_UNDEFINED;

    private final int mMinimizedVisibleSize;
    private boolean mIsMinimized;

    public PipSnapAlgorithm(Context context) {
        Resources res = context.getResources();
        mContext = context;
        mMinimizedVisibleSize = res.getDimensionPixelSize(
                com.android.internal.R.dimen.pip_minimized_visible_size);
        mDefaultSizePercent = res.getFloat(
                com.android.internal.R.dimen.config_pictureInPictureDefaultSizePercent);
        mMaxAspectRatioForMinSize = res.getFloat(
                com.android.internal.R.dimen.config_pictureInPictureAspectRatioLimitForMinSize);
        mMinAspectRatioForMinSize = 1f / mMaxAspectRatioForMinSize;
        mFlingDeceleration = mContext.getResources().getDimensionPixelSize(
                com.android.internal.R.dimen.pip_fling_deceleration);
        onConfigurationChanged();
    }

    /**
     * Updates the snap algorithm when the configuration changes.
     */
    public void onConfigurationChanged() {
        Resources res = mContext.getResources();
        mOrientation = res.getConfiguration().orientation;
        mSnapMode = res.getInteger(com.android.internal.R.integer.config_pictureInPictureSnapMode);
        calculateSnapTargets();
    }

    /**
     * Sets the PIP's minimized state.
     */
    public void setMinimized(boolean isMinimized) {
        mIsMinimized = isMinimized;
    }

    /**
     * @return the closest absolute snap stack bounds for the given {@param stackBounds} moving at
     * the given {@param velocityX} and {@param velocityY}.  The {@param movementBounds} should be
     * those for the given {@param stackBounds}.
     */
    public Rect findClosestSnapBounds(Rect movementBounds, Rect stackBounds, float velocityX,
            float velocityY, Point dragStartPosition) {
        final Rect intersectStackBounds = new Rect(stackBounds);
        final Point intersect = getEdgeIntersect(stackBounds, movementBounds, velocityX, velocityY,
                dragStartPosition);
        intersectStackBounds.offsetTo(intersect.x, intersect.y);
        return findClosestSnapBounds(movementBounds, intersectStackBounds);
    }

    /**
     * @return The point along the {@param movementBounds} that the PIP would intersect with based
     *         on the provided {@param velX}, {@param velY} along with the position of the PIP when
     *         the gesture started, {@param dragStartPosition}.
     */
    public Point getEdgeIntersect(Rect stackBounds, Rect movementBounds, float velX, float velY,
            Point dragStartPosition) {
        final boolean isLandscape = mOrientation == Configuration.ORIENTATION_LANDSCAPE;
        final int x = stackBounds.left;
        final int y = stackBounds.top;

        // Find the line of movement the PIP is on. Line defined by: y = slope * x + yIntercept
        final float slope = velY / velX; // slope = rise / run
        final float yIntercept = y - slope * x; // rearrange line equation for yIntercept
        // The PIP can have two intercept points:
        // 1) Where the line intersects with one of the edges of the screen (vertical line)
        Point vertPoint = new Point();
        // 2) Where the line intersects with the top or bottom of the screen (horizontal line)
        Point horizPoint = new Point();

        // Find the vertical line intersection, x will be one of the edges
        vertPoint.x = velX > 0 ? movementBounds.right : movementBounds.left;
        // Sub in x in our line equation to determine y position
        vertPoint.y = findY(slope, yIntercept, vertPoint.x);

        // Find the horizontal line intersection, y will be the top or bottom of the screen
        horizPoint.y = velY > 0 ? movementBounds.bottom : movementBounds.top;
        // Sub in y in our line equation to determine x position
        horizPoint.x = findX(slope, yIntercept, horizPoint.y);

        // Now pick one of these points -- first determine if we're flinging along the current edge.
        // Only fling along current edge if it's a direction with space for the PIP to move to
        int maxDistance;
        if (isLandscape) {
            maxDistance = velX > 0
                    ? movementBounds.right - stackBounds.left
                    : stackBounds.left - movementBounds.left;
        } else {
            maxDistance = velY > 0
                    ? movementBounds.bottom - stackBounds.top
                    : stackBounds.top - movementBounds.top;
        }
        if (maxDistance > 0) {
            // Only fling along the current edge if the start and end point are on the same side
            final int startPoint = isLandscape ? dragStartPosition.y : dragStartPosition.x;
            final int endPoint = isLandscape ? horizPoint.y : horizPoint.x;
            final int center = movementBounds.centerX();
            if ((startPoint < center && endPoint < center)
                    || (startPoint > center && endPoint > center)) {
                // We are flinging along the current edge, figure out how far it should travel
                // based on velocity and assumed deceleration.
                int distance = (int) (0 - Math.pow(isLandscape ? velX : velY, 2))
                        / (2 * mFlingDeceleration);
                distance = Math.min(distance, maxDistance);
                // Adjust the point for the distance
                if (isLandscape) {
                    horizPoint.x = stackBounds.left + (velX > 0 ? distance : -distance);
                } else {
                    horizPoint.y = stackBounds.top + (velY > 0 ? distance : -distance);
                }
                return horizPoint;
            }
        }
        // If we're not flinging along the current edge, find the closest point instead.
        final double distanceVert = Math.hypot(vertPoint.x - x, vertPoint.y - y);
        final double distanceHoriz = Math.hypot(horizPoint.x - x, horizPoint.y - y);
        // Ensure that we're actually going somewhere
        if (distanceVert == 0) {
            return horizPoint;
        }
        if (distanceHoriz == 0) {
            return vertPoint;
        }
        // Otherwise use the closest point
        return Math.abs(distanceVert) > Math.abs(distanceHoriz) ? horizPoint : vertPoint;
    }

    private int findY(float slope, float yIntercept, float x) {
        return (int) ((slope * x) + yIntercept);
    }

    private int findX(float slope, float yIntercept, float y) {
        return (int) ((y - yIntercept) / slope);
    }

    /**
     * @return the closest absolute snap stack bounds for the given {@param stackBounds}.  The
     * {@param movementBounds} should be those for the given {@param stackBounds}.
     */
    public Rect findClosestSnapBounds(Rect movementBounds, Rect stackBounds) {
        final Rect pipBounds = new Rect(movementBounds.left, movementBounds.top,
                movementBounds.right + stackBounds.width(),
                movementBounds.bottom + stackBounds.height());
        final Rect newBounds = new Rect(stackBounds);
        if (mSnapMode == SNAP_MODE_LONG_EDGE_MAGNET_CORNERS
                || mSnapMode == SNAP_MODE_EDGE_MAGNET_CORNERS) {
            final Rect tmpBounds = new Rect();
            final Point[] snapTargets = new Point[mSnapGravities.size()];
            for (int i = 0; i < mSnapGravities.size(); i++) {
                Gravity.apply(mSnapGravities.get(i), stackBounds.width(), stackBounds.height(),
                        pipBounds, 0, 0, tmpBounds);
                snapTargets[i] = new Point(tmpBounds.left, tmpBounds.top);
            }
            Point snapTarget = findClosestPoint(stackBounds.left, stackBounds.top, snapTargets);
            float distance = distanceToPoint(snapTarget, stackBounds.left, stackBounds.top);
            final float thresh = Math.max(stackBounds.width(), stackBounds.height())
                    * CORNER_MAGNET_THRESHOLD;
            if (distance < thresh) {
                newBounds.offsetTo(snapTarget.x, snapTarget.y);
            } else {
                snapRectToClosestEdge(stackBounds, movementBounds, newBounds);
            }
        } else if (mSnapMode == SNAP_MODE_EDGE) {
            // Find the closest edge to the given stack bounds and snap to it
            snapRectToClosestEdge(stackBounds, movementBounds, newBounds);
        } else {
            // Find the closest snap point
            final Rect tmpBounds = new Rect();
            final Point[] snapTargets = new Point[mSnapGravities.size()];
            for (int i = 0; i < mSnapGravities.size(); i++) {
                Gravity.apply(mSnapGravities.get(i), stackBounds.width(), stackBounds.height(),
                        pipBounds, 0, 0, tmpBounds);
                snapTargets[i] = new Point(tmpBounds.left, tmpBounds.top);
            }
            Point snapTarget = findClosestPoint(stackBounds.left, stackBounds.top, snapTargets);
            newBounds.offsetTo(snapTarget.x, snapTarget.y);
        }
        return newBounds;
    }

    /**
     * Applies the offset to the {@param stackBounds} to adjust it to a minimized state.
     */
    public void applyMinimizedOffset(Rect stackBounds, Rect movementBounds, Point displaySize,
            Rect stableInsets) {
        if (stackBounds.left <= movementBounds.centerX()) {
            stackBounds.offsetTo(stableInsets.left + mMinimizedVisibleSize - stackBounds.width(),
                    stackBounds.top);
        } else {
            stackBounds.offsetTo(displaySize.x - stableInsets.right - mMinimizedVisibleSize,
                    stackBounds.top);
        }
    }

    /**
     * @return returns a fraction that describes where along the {@param movementBounds} the
     *         {@param stackBounds} are. If the {@param stackBounds} are not currently on the
     *         {@param movementBounds} exactly, then they will be snapped to the movement bounds.
     *
     *         The fraction is defined in a clockwise fashion against the {@param movementBounds}:
     *
     *            0   1
     *          4 +---+ 1
     *            |   |
     *          3 +---+ 2
     *            3   2
     */
    public float getSnapFraction(Rect stackBounds, Rect movementBounds) {
        final Rect tmpBounds = new Rect();
        snapRectToClosestEdge(stackBounds, movementBounds, tmpBounds);
        final float widthFraction = (float) (tmpBounds.left - movementBounds.left) /
                movementBounds.width();
        final float heightFraction = (float) (tmpBounds.top - movementBounds.top) /
                movementBounds.height();
        if (tmpBounds.top == movementBounds.top) {
            return widthFraction;
        } else if (tmpBounds.left == movementBounds.right) {
            return 1f + heightFraction;
        } else if (tmpBounds.top == movementBounds.bottom) {
            return 2f + (1f - widthFraction);
        } else {
            return 3f + (1f - heightFraction);
        }
    }

    /**
     * Moves the {@param stackBounds} along the {@param movementBounds} to the given snap fraction.
     * See {@link #getSnapFraction(Rect, Rect)}.
     *
     * The fraction is define in a clockwise fashion against the {@param movementBounds}:
     *
     *    0   1
     *  4 +---+ 1
     *    |   |
     *  3 +---+ 2
     *    3   2
     */
    public void applySnapFraction(Rect stackBounds, Rect movementBounds, float snapFraction) {
        if (snapFraction < 1f) {
            int offset = movementBounds.left + (int) (snapFraction * movementBounds.width());
            stackBounds.offsetTo(offset, movementBounds.top);
        } else if (snapFraction < 2f) {
            snapFraction -= 1f;
            int offset = movementBounds.top + (int) (snapFraction * movementBounds.height());
            stackBounds.offsetTo(movementBounds.right, offset);
        } else if (snapFraction < 3f) {
            snapFraction -= 2f;
            int offset = movementBounds.left + (int) ((1f - snapFraction) * movementBounds.width());
            stackBounds.offsetTo(offset, movementBounds.bottom);
        } else {
            snapFraction -= 3f;
            int offset = movementBounds.top + (int) ((1f - snapFraction) * movementBounds.height());
            stackBounds.offsetTo(movementBounds.left, offset);
        }
    }

    /**
     * Adjusts {@param movementBoundsOut} so that it is the movement bounds for the given
     * {@param stackBounds}.
     */
    public void getMovementBounds(Rect stackBounds, Rect insetBounds, Rect movementBoundsOut,
            int bottomOffset) {
        // Adjust the right/bottom to ensure the stack bounds never goes offscreen
        movementBoundsOut.set(insetBounds);
        movementBoundsOut.right = Math.max(insetBounds.left, insetBounds.right -
                stackBounds.width());
        movementBoundsOut.bottom = Math.max(insetBounds.top, insetBounds.bottom -
                stackBounds.height());
        movementBoundsOut.bottom -= bottomOffset;
    }

    /**
     * @return the size of the PiP at the given {@param aspectRatio}, ensuring that the minimum edge
     * is at least {@param minEdgeSize}.
     */
    public Size getSizeForAspectRatio(float aspectRatio, float minEdgeSize, int displayWidth,
            int displayHeight) {
        final int smallestDisplaySize = Math.min(displayWidth, displayHeight);
        final int minSize = (int) Math.max(minEdgeSize, smallestDisplaySize * mDefaultSizePercent);

        final int width;
        final int height;
        if (aspectRatio <= mMinAspectRatioForMinSize || aspectRatio > mMaxAspectRatioForMinSize) {
            // Beyond these points, we can just use the min size as the shorter edge
            if (aspectRatio <= 1) {
                // Portrait, width is the minimum size
                width = minSize;
                height = Math.round(width / aspectRatio);
            } else {
                // Landscape, height is the minimum size
                height = minSize;
                width = Math.round(height * aspectRatio);
            }
        } else {
            // Within these points, we ensure that the bounds fit within the radius of the limits
            // at the points
            final float widthAtMaxAspectRatioForMinSize = mMaxAspectRatioForMinSize * minSize;
            final float radius = PointF.length(widthAtMaxAspectRatioForMinSize, minSize);
            height = (int) Math.round(Math.sqrt((radius * radius) /
                    (aspectRatio * aspectRatio + 1)));
            width = Math.round(height * aspectRatio);
        }
        return new Size(width, height);
    }

    /**
     * @return the closest point in {@param points} to the given {@param x} and {@param y}.
     */
    private Point findClosestPoint(int x, int y, Point[] points) {
        Point closestPoint = null;
        float minDistance = Float.MAX_VALUE;
        for (Point p : points) {
            float distance = distanceToPoint(p, x, y);
            if (distance < minDistance) {
                closestPoint = p;
                minDistance = distance;
            }
        }
        return closestPoint;
    }

    /**
     * Snaps the {@param stackBounds} to the closest edge of the {@param movementBounds} and writes
     * the new bounds out to {@param boundsOut}.
     */
    private void snapRectToClosestEdge(Rect stackBounds, Rect movementBounds, Rect boundsOut) {
        // If the stackBounds are minimized, then it should only be snapped back horizontally
        final int boundedLeft = Math.max(movementBounds.left, Math.min(movementBounds.right,
                stackBounds.left));
        final int boundedTop = Math.max(movementBounds.top, Math.min(movementBounds.bottom,
                stackBounds.top));
        boundsOut.set(stackBounds);
        if (mIsMinimized) {
            boundsOut.offsetTo(boundedLeft, boundedTop);
            return;
        }

        // Otherwise, just find the closest edge
        final int fromLeft = Math.abs(stackBounds.left - movementBounds.left);
        final int fromTop = Math.abs(stackBounds.top - movementBounds.top);
        final int fromRight = Math.abs(movementBounds.right - stackBounds.left);
        final int fromBottom = Math.abs(movementBounds.bottom - stackBounds.top);
        int shortest;
        if (mSnapMode == SNAP_MODE_LONG_EDGE_MAGNET_CORNERS) {
            // Only check longest edges
            shortest = (mOrientation == Configuration.ORIENTATION_LANDSCAPE)
                    ? Math.min(fromTop, fromBottom)
                    : Math.min(fromLeft, fromRight);
        } else {
            shortest = Math.min(Math.min(fromLeft, fromRight), Math.min(fromTop, fromBottom));
        }
        if (shortest == fromLeft) {
            boundsOut.offsetTo(movementBounds.left, boundedTop);
        } else if (shortest == fromTop) {
            boundsOut.offsetTo(boundedLeft, movementBounds.top);
        } else if (shortest == fromRight) {
            boundsOut.offsetTo(movementBounds.right, boundedTop);
        } else {
            boundsOut.offsetTo(boundedLeft, movementBounds.bottom);
        }
    }

    /**
     * @return the distance between point {@param p} and the given {@param x} and {@param y}.
     */
    private float distanceToPoint(Point p, int x, int y) {
        return PointF.length(p.x - x, p.y - y);
    }

    /**
     * Calculate the snap targets for the discrete snap modes.
     */
    private void calculateSnapTargets() {
        mSnapGravities.clear();
        switch (mSnapMode) {
            case SNAP_MODE_CORNERS_AND_SIDES:
                if (mOrientation == Configuration.ORIENTATION_LANDSCAPE) {
                    mSnapGravities.add(Gravity.TOP | Gravity.CENTER_HORIZONTAL);
                    mSnapGravities.add(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL);
                } else {
                    mSnapGravities.add(Gravity.CENTER_VERTICAL | Gravity.LEFT);
                    mSnapGravities.add(Gravity.CENTER_VERTICAL | Gravity.RIGHT);
                }
                // Fall through
            case SNAP_MODE_CORNERS_ONLY:
            case SNAP_MODE_EDGE_MAGNET_CORNERS:
            case SNAP_MODE_LONG_EDGE_MAGNET_CORNERS:
                mSnapGravities.add(Gravity.TOP | Gravity.LEFT);
                mSnapGravities.add(Gravity.TOP | Gravity.RIGHT);
                mSnapGravities.add(Gravity.BOTTOM | Gravity.LEFT);
                mSnapGravities.add(Gravity.BOTTOM | Gravity.RIGHT);
                break;
            default:
                // Skip otherwise
                break;
        }
    }

    public void dump(PrintWriter pw, String prefix) {
        final String innerPrefix = prefix + "  ";
        pw.println(prefix + PipSnapAlgorithm.class.getSimpleName());
        pw.println(innerPrefix + "mSnapMode=" + mSnapMode);
        pw.println(innerPrefix + "mOrientation=" + mOrientation);
        pw.println(innerPrefix + "mMinimizedVisibleSize=" + mMinimizedVisibleSize);
        pw.println(innerPrefix + "mIsMinimized=" + mIsMinimized);
    }
}
