/*
 * Copyright (C) 2014 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.systemui.recents.views;

import android.annotation.IntDef;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Path;
import android.graphics.Rect;
import android.util.ArraySet;
import android.util.MutableFloat;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.view.ViewDebug;

import com.android.systemui.R;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsActivityLaunchState;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.RecentsDebugFlags;
import com.android.systemui.recents.misc.FreePathInterpolator;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
import com.android.systemui.recents.views.grid.TaskGridLayoutAlgorithm;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;

/**
 * Used to describe a visible range that can be normalized to [0, 1].
 */
class Range {
    final float relativeMin;
    final float relativeMax;
    float origin;
    float min;
    float max;

    public Range(float relMin, float relMax) {
        min = relativeMin = relMin;
        max = relativeMax = relMax;
    }

    /**
     * Offsets this range to a given absolute position.
     */
    public void offset(float x) {
        this.origin = x;
        min = x + relativeMin;
        max = x + relativeMax;
    }

    /**
     * Returns x normalized to the range 0 to 1 such that 0 = min, 0.5 = origin and 1 = max
     *
     * @param x is an absolute value in the same domain as origin
     */
    public float getNormalizedX(float x) {
        if (x < origin) {
            return 0.5f + 0.5f * (x - origin) / -relativeMin;
        } else {
            return 0.5f + 0.5f * (x - origin) / relativeMax;
        }
    }

    /**
     * Given a normalized {@param x} value in this range, projected onto the full range to get an
     * absolute value about the given {@param origin}.
     */
    public float getAbsoluteX(float normX) {
        if (normX < 0.5f) {
            return (normX - 0.5f) / 0.5f * -relativeMin;
        } else {
            return (normX - 0.5f) / 0.5f * relativeMax;
        }
    }

    /**
     * Returns whether a value at an absolute x would be within range.
     */
    public boolean isInRange(float absX) {
        return (absX >= Math.floor(min)) && (absX <= Math.ceil(max));
    }
}

/**
 * The layout logic for a TaskStackView.  This layout needs to be able to calculate the stack layout
 * without an activity-specific context only with the information passed in.  This layout can have
 * two states focused and unfocused, and in the focused state, there is a task that is displayed
 * more prominently in the stack.
 */
public class TaskStackLayoutAlgorithm {

    private static final String TAG = "TaskStackLayoutAlgorithm";

    // The distribution of view bounds alpha
    // XXX: This is a hack because you can currently set the max alpha to be > 1f
    public static final float OUTLINE_ALPHA_MIN_VALUE = 0f;
    public static final float OUTLINE_ALPHA_MAX_VALUE = 2f;

    // The medium/maximum dim on the tasks
    private static final float MED_DIM = 0.15f;
    private static final float MAX_DIM = 0.25f;

    // The various focus states
    public static final int STATE_FOCUSED = 1;
    public static final int STATE_UNFOCUSED = 0;

    // The side that an offset is anchored
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({FROM_TOP, FROM_BOTTOM})
    public @interface AnchorSide {}
    private static final int FROM_TOP = 0;
    private static final int FROM_BOTTOM = 1;

    // The extent that we care about when calculating fractions
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({WIDTH, HEIGHT})
    public @interface Extent {}
    private static final int WIDTH = 0;
    private static final int HEIGHT = 1;

    public interface TaskStackLayoutAlgorithmCallbacks {
        void onFocusStateChanged(int prevFocusState, int curFocusState);
    }

    /**
     * The various stack/freeform states.
     */
    public static class StackState {

        public static final StackState FREEFORM_ONLY = new StackState(1f, 255);
        public static final StackState STACK_ONLY = new StackState(0f, 0);
        public static final StackState SPLIT = new StackState(0.5f, 255);

        public final float freeformHeightPct;
        public final int freeformBackgroundAlpha;

        /**
         * @param freeformHeightPct the percentage of the stack height (not including paddings) to
         *                          allocate to the freeform workspace
         * @param freeformBackgroundAlpha the background alpha for the freeform workspace
         */
        private StackState(float freeformHeightPct, int freeformBackgroundAlpha) {
            this.freeformHeightPct = freeformHeightPct;
            this.freeformBackgroundAlpha = freeformBackgroundAlpha;
        }

        /**
         * Resolves the stack state for the layout given a task stack.
         */
        public static StackState getStackStateForStack(TaskStack stack) {
            SystemServicesProxy ssp = Recents.getSystemServices();
            boolean hasFreeformWorkspaces = ssp.hasFreeformWorkspaceSupport();
            int freeformCount = stack.getFreeformTaskCount();
            int stackCount = stack.getStackTaskCount();
            if (hasFreeformWorkspaces && stackCount > 0 && freeformCount > 0) {
                return SPLIT;
            } else if (hasFreeformWorkspaces && freeformCount > 0) {
                return FREEFORM_ONLY;
            } else {
                return STACK_ONLY;
            }
        }

        /**
         * Computes the freeform and stack rect for this state.
         *
         * @param freeformRectOut the freeform rect to be written out
         * @param stackRectOut the stack rect, we only write out the top of the stack
         * @param taskStackBounds the full rect that the freeform rect can take up
         */
        public void computeRects(Rect freeformRectOut, Rect stackRectOut,
                Rect taskStackBounds, int topMargin, int freeformGap, int stackBottomOffset) {
            // The freeform height is the visible height (not including system insets) - padding
            // above freeform and below stack - gap between the freeform and stack
            int availableHeight = taskStackBounds.height() - topMargin - stackBottomOffset;
            int ffPaddedHeight = (int) (availableHeight * freeformHeightPct);
            int ffHeight = Math.max(0, ffPaddedHeight - freeformGap);
            freeformRectOut.set(taskStackBounds.left,
                    taskStackBounds.top + topMargin,
                    taskStackBounds.right,
                    taskStackBounds.top + topMargin + ffHeight);
            stackRectOut.set(taskStackBounds.left,
                    taskStackBounds.top,
                    taskStackBounds.right,
                    taskStackBounds.bottom);
            if (ffPaddedHeight > 0) {
                stackRectOut.top += ffPaddedHeight;
            } else {
                stackRectOut.top += topMargin;
            }
        }
    }

    /**
     * @return True if we should use the grid layout.
     */
    boolean useGridLayout() {
        return Recents.getConfiguration().isGridEnabled;
    }

    // A report of the visibility state of the stack
    public class VisibilityReport {
        public int numVisibleTasks;
        public int numVisibleThumbnails;

        /** Package level ctor */
        VisibilityReport(int tasks, int thumbnails) {
            numVisibleTasks = tasks;
            numVisibleThumbnails = thumbnails;
        }
    }

    Context mContext;
    private StackState mState = StackState.SPLIT;
    private TaskStackLayoutAlgorithmCallbacks mCb;

    // The task bounds (untransformed) for layout.  This rect is anchored at mTaskRoot.
    @ViewDebug.ExportedProperty(category="recents")
    public Rect mTaskRect = new Rect();
    // The freeform workspace bounds, inset by the top system insets and is a fixed height
    @ViewDebug.ExportedProperty(category="recents")
    public Rect mFreeformRect = new Rect();
    // The stack bounds, inset from the top system insets, and runs to the bottom of the screen
    @ViewDebug.ExportedProperty(category="recents")
    public Rect mStackRect = new Rect();
    // This is the current system insets
    @ViewDebug.ExportedProperty(category="recents")
    public Rect mSystemInsets = new Rect();

    // The visible ranges when the stack is focused and unfocused
    private Range mUnfocusedRange;
    private Range mFocusedRange;

    // This is the bounds of the stack action above the stack rect
    @ViewDebug.ExportedProperty(category="recents")
    private Rect mStackActionButtonRect = new Rect();
    // The base top margin for the stack from the system insets
    @ViewDebug.ExportedProperty(category="recents")
    private int mBaseTopMargin;
    // The base side margin for the stack from the system insets
    @ViewDebug.ExportedProperty(category="recents")
    private int mBaseSideMargin;
    // The base bottom margin for the stack from the system insets
    @ViewDebug.ExportedProperty(category="recents")
    private int mBaseBottomMargin;
    private int mMinMargin;

    // The gap between the freeform and stack layouts
    @ViewDebug.ExportedProperty(category="recents")
    private int mFreeformStackGap;

    // The initial offset that the focused task is from the top
    @ViewDebug.ExportedProperty(category="recents")
    private int mInitialTopOffset;
    private int mBaseInitialTopOffset;
    // The initial offset that the launch-from task is from the bottom
    @ViewDebug.ExportedProperty(category="recents")
    private int mInitialBottomOffset;
    private int mBaseInitialBottomOffset;

    // The height between the top margin and the top of the focused task
    @ViewDebug.ExportedProperty(category="recents")
    private int mFocusedTopPeekHeight;
    // The height between the bottom margin and the top of task in front of the focused task
    @ViewDebug.ExportedProperty(category="recents")
    private int mFocusedBottomPeekHeight;

    // The offset from the bottom of the stack to the bottom of the bounds when the stack is
    // scrolled to the front
    @ViewDebug.ExportedProperty(category="recents")
    private int mStackBottomOffset;

    // The paths defining the motion of the tasks when the stack is focused and unfocused
    private Path mUnfocusedCurve;
    private Path mFocusedCurve;
    private FreePathInterpolator mUnfocusedCurveInterpolator;
    private FreePathInterpolator mFocusedCurveInterpolator;

    // The paths defining the distribution of the dim to apply to tasks in the stack when focused
    // and unfocused
    private Path mUnfocusedDimCurve;
    private Path mFocusedDimCurve;
    private FreePathInterpolator mUnfocusedDimCurveInterpolator;
    private FreePathInterpolator mFocusedDimCurveInterpolator;

    // The state of the stack focus (0..1), which controls the transition of the stack from the
    // focused to non-focused state
    @ViewDebug.ExportedProperty(category="recents")
    private int mFocusState;

    // The smallest scroll progress, at this value, the back most task will be visible
    @ViewDebug.ExportedProperty(category="recents")
    float mMinScrollP;
    // The largest scroll progress, at this value, the front most task will be visible above the
    // navigation bar
    @ViewDebug.ExportedProperty(category="recents")
    float mMaxScrollP;
    // The initial progress that the scroller is set when you first enter recents
    @ViewDebug.ExportedProperty(category="recents")
    float mInitialScrollP;
    // The task progress for the front-most task in the stack
    @ViewDebug.ExportedProperty(category="recents")
    float mFrontMostTaskP;

    // The last computed task counts
    @ViewDebug.ExportedProperty(category="recents")
    int mNumStackTasks;
    @ViewDebug.ExportedProperty(category="recents")
    int mNumFreeformTasks;

    // The min/max z translations
    @ViewDebug.ExportedProperty(category="recents")
    int mMinTranslationZ;
    @ViewDebug.ExportedProperty(category="recents")
    public int mMaxTranslationZ;

    // Optimization, allows for quick lookup of task -> index
    private SparseIntArray mTaskIndexMap = new SparseIntArray();
    private SparseArray<Float> mTaskIndexOverrideMap = new SparseArray<>();

    // The freeform workspace layout
    FreeformWorkspaceLayoutAlgorithm mFreeformLayoutAlgorithm;
    TaskGridLayoutAlgorithm mTaskGridLayoutAlgorithm;

    // The transform to place TaskViews at the front and back of the stack respectively
    TaskViewTransform mBackOfStackTransform = new TaskViewTransform();
    TaskViewTransform mFrontOfStackTransform = new TaskViewTransform();

    public TaskStackLayoutAlgorithm(Context context, TaskStackLayoutAlgorithmCallbacks cb) {
        Resources res = context.getResources();
        mContext = context;
        mCb = cb;
        mFreeformLayoutAlgorithm = new FreeformWorkspaceLayoutAlgorithm(context);
        mTaskGridLayoutAlgorithm = new TaskGridLayoutAlgorithm(context);
        reloadOnConfigurationChange(context);
    }

    /**
     * Reloads the layout for the current configuration.
     */
    public void reloadOnConfigurationChange(Context context) {
        Resources res = context.getResources();
        mFocusedRange = new Range(res.getFloat(R.integer.recents_layout_focused_range_min),
                res.getFloat(R.integer.recents_layout_focused_range_max));
        mUnfocusedRange = new Range(res.getFloat(R.integer.recents_layout_unfocused_range_min),
                res.getFloat(R.integer.recents_layout_unfocused_range_max));
        mFocusState = getInitialFocusState();
        mFocusedTopPeekHeight = res.getDimensionPixelSize(R.dimen.recents_layout_top_peek_size);
        mFocusedBottomPeekHeight =
                res.getDimensionPixelSize(R.dimen.recents_layout_bottom_peek_size);
        mMinTranslationZ = res.getDimensionPixelSize(R.dimen.recents_layout_z_min);
        mMaxTranslationZ = res.getDimensionPixelSize(R.dimen.recents_layout_z_max);
        mBaseInitialTopOffset = getDimensionForDevice(context,
                R.dimen.recents_layout_initial_top_offset_phone_port,
                R.dimen.recents_layout_initial_top_offset_phone_land,
                R.dimen.recents_layout_initial_top_offset_tablet,
                R.dimen.recents_layout_initial_top_offset_tablet,
                R.dimen.recents_layout_initial_top_offset_tablet,
                R.dimen.recents_layout_initial_top_offset_tablet,
                R.dimen.recents_layout_initial_top_offset_tablet);
        mBaseInitialBottomOffset = getDimensionForDevice(context,
                R.dimen.recents_layout_initial_bottom_offset_phone_port,
                R.dimen.recents_layout_initial_bottom_offset_phone_land,
                R.dimen.recents_layout_initial_bottom_offset_tablet,
                R.dimen.recents_layout_initial_bottom_offset_tablet,
                R.dimen.recents_layout_initial_bottom_offset_tablet,
                R.dimen.recents_layout_initial_bottom_offset_tablet,
                R.dimen.recents_layout_initial_bottom_offset_tablet);
        mFreeformLayoutAlgorithm.reloadOnConfigurationChange(context);
        mTaskGridLayoutAlgorithm.reloadOnConfigurationChange(context);
        mMinMargin = res.getDimensionPixelSize(R.dimen.recents_layout_min_margin);
        mBaseTopMargin = getDimensionForDevice(context,
                R.dimen.recents_layout_top_margin_phone,
                R.dimen.recents_layout_top_margin_tablet,
                R.dimen.recents_layout_top_margin_tablet_xlarge,
                R.dimen.recents_layout_top_margin_tablet);
        mBaseSideMargin = getDimensionForDevice(context,
                R.dimen.recents_layout_side_margin_phone,
                R.dimen.recents_layout_side_margin_tablet,
                R.dimen.recents_layout_side_margin_tablet_xlarge,
                R.dimen.recents_layout_side_margin_tablet);
        mBaseBottomMargin = res.getDimensionPixelSize(R.dimen.recents_layout_bottom_margin);
        mFreeformStackGap =
                res.getDimensionPixelSize(R.dimen.recents_freeform_layout_bottom_margin);
    }

    /**
     * Resets this layout when the stack view is reset.
     */
    public void reset() {
        mTaskIndexOverrideMap.clear();
        setFocusState(getInitialFocusState());
    }

    /**
     * Sets the system insets.
     */
    public boolean setSystemInsets(Rect systemInsets) {
        boolean changed = !mSystemInsets.equals(systemInsets);
        mSystemInsets.set(systemInsets);
        mTaskGridLayoutAlgorithm.setSystemInsets(systemInsets);
        return changed;
    }

    /**
     * Sets the focused state.
     */
    public void setFocusState(int focusState) {
        int prevFocusState = mFocusState;
        mFocusState = focusState;
        updateFrontBackTransforms();
        if (mCb != null) {
            mCb.onFocusStateChanged(prevFocusState, focusState);
        }
    }

    /**
     * Gets the focused state.
     */
    public int getFocusState() {
        return mFocusState;
    }

    /**
     * Computes the stack and task rects.  The given task stack bounds already has the top/right
     * insets and left/right padding already applied.
     */
    public void initialize(Rect displayRect, Rect windowRect, Rect taskStackBounds,
            StackState state) {
        Rect lastStackRect = new Rect(mStackRect);

        int topMargin = getScaleForExtent(windowRect, displayRect, mBaseTopMargin, mMinMargin, HEIGHT);
        int bottomMargin = getScaleForExtent(windowRect, displayRect, mBaseBottomMargin, mMinMargin,
                HEIGHT);
        mInitialTopOffset = getScaleForExtent(windowRect, displayRect, mBaseInitialTopOffset,
                mMinMargin, HEIGHT);
        mInitialBottomOffset = mBaseInitialBottomOffset;

        // Compute the stack bounds
        mState = state;
        mStackBottomOffset = mSystemInsets.bottom + bottomMargin;
        state.computeRects(mFreeformRect, mStackRect, taskStackBounds, topMargin,
                mFreeformStackGap, mStackBottomOffset);

        // The stack action button will take the full un-padded header space above the stack
        mStackActionButtonRect.set(mStackRect.left, mStackRect.top - topMargin,
                mStackRect.right, mStackRect.top + mFocusedTopPeekHeight);

        // Anchor the task rect top aligned to the stack rect
        int height = mStackRect.height() - mInitialTopOffset - mStackBottomOffset;
        mTaskRect.set(mStackRect.left, mStackRect.top, mStackRect.right, mStackRect.top + height);

        // Short circuit here if the stack rects haven't changed so we don't do all the work below
        if (!lastStackRect.equals(mStackRect)) {
            // Reinitialize the focused and unfocused curves
            mUnfocusedCurve = constructUnfocusedCurve();
            mUnfocusedCurveInterpolator = new FreePathInterpolator(mUnfocusedCurve);
            mFocusedCurve = constructFocusedCurve();
            mFocusedCurveInterpolator = new FreePathInterpolator(mFocusedCurve);
            mUnfocusedDimCurve = constructUnfocusedDimCurve();
            mUnfocusedDimCurveInterpolator = new FreePathInterpolator(mUnfocusedDimCurve);
            mFocusedDimCurve = constructFocusedDimCurve();
            mFocusedDimCurveInterpolator = new FreePathInterpolator(mFocusedDimCurve);

            updateFrontBackTransforms();
        }

        // Initialize the grid layout
        mTaskGridLayoutAlgorithm.initialize(windowRect);
    }

    /**
     * Computes the minimum and maximum scroll progress values and the progress values for each task
     * in the stack.
     */
    void update(TaskStack stack, ArraySet<Task.TaskKey> ignoreTasksSet) {
        SystemServicesProxy ssp = Recents.getSystemServices();
        RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();

        // Clear the progress map
        mTaskIndexMap.clear();

        // Return early if we have no tasks
        ArrayList<Task> tasks = stack.getStackTasks();
        if (tasks.isEmpty()) {
            mFrontMostTaskP = 0;
            mMinScrollP = mMaxScrollP = mInitialScrollP = 0;
            mNumStackTasks = mNumFreeformTasks = 0;
            return;
        }

        // Filter the set of freeform and stack tasks
        ArrayList<Task> freeformTasks = new ArrayList<>();
        ArrayList<Task> stackTasks = new ArrayList<>();
        for (int i = 0; i < tasks.size(); i++) {
            Task task = tasks.get(i);
            if (ignoreTasksSet.contains(task.key)) {
                continue;
            }
            if (task.isFreeformTask()) {
                freeformTasks.add(task);
            } else {
                stackTasks.add(task);
            }
        }
        mNumStackTasks = stackTasks.size();
        mNumFreeformTasks = freeformTasks.size();

        // Put each of the tasks in the progress map at a fixed index (does not need to actually
        // map to a scroll position, just by index)
        int taskCount = stackTasks.size();
        for (int i = 0; i < taskCount; i++) {
            Task task = stackTasks.get(i);
            mTaskIndexMap.put(task.key.id, i);
        }

        // Update the freeform tasks
        if (!freeformTasks.isEmpty()) {
            mFreeformLayoutAlgorithm.update(freeformTasks, this);
        }

        // Calculate the min/max/initial scroll
        Task launchTask = stack.getLaunchTarget();
        int launchTaskIndex = launchTask != null
                ? stack.indexOfStackTask(launchTask)
                : mNumStackTasks - 1;
        if (getInitialFocusState() == STATE_FOCUSED) {
            int maxBottomOffset = mStackBottomOffset + mTaskRect.height();
            float maxBottomNormX = getNormalizedXFromFocusedY(maxBottomOffset, FROM_BOTTOM);
            mFocusedRange.offset(0f);
            mMinScrollP = 0;
            mMaxScrollP = Math.max(mMinScrollP, (mNumStackTasks - 1) -
                    Math.max(0, mFocusedRange.getAbsoluteX(maxBottomNormX)));
            if (launchState.launchedFromHome) {
                mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
            } else {
                mInitialScrollP = Utilities.clamp(launchTaskIndex - 1, mMinScrollP, mMaxScrollP);
            }
        } else if (!ssp.hasFreeformWorkspaceSupport() && mNumStackTasks == 1) {
            // If there is one stack task, ignore the min/max/initial scroll positions
            mMinScrollP = 0;
            mMaxScrollP = 0;
            mInitialScrollP = 0;
        } else {
            // Set the max scroll to be the point where the front most task is visible with the
            // stack bottom offset
            int maxBottomOffset = mStackBottomOffset + mTaskRect.height();
            float maxBottomNormX = getNormalizedXFromUnfocusedY(maxBottomOffset, FROM_BOTTOM);
            mUnfocusedRange.offset(0f);
            mMinScrollP = 0;
            mMaxScrollP = Math.max(mMinScrollP, (mNumStackTasks - 1) -
                    Math.max(0, mUnfocusedRange.getAbsoluteX(maxBottomNormX)));
            boolean scrollToFront = launchState.launchedFromHome ||
                    launchState.launchedViaDockGesture;
            if (launchState.launchedFromBlacklistedApp) {
                mInitialScrollP = mMaxScrollP;
            } else if (launchState.launchedWithAltTab) {
                mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
            } else if (scrollToFront) {
                mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
            } else {
                // We are overriding the initial two task positions, so set the initial scroll
                // position to match the second task (aka focused task) position
                float initialTopNormX = getNormalizedXFromUnfocusedY(mInitialTopOffset, FROM_TOP);
                mInitialScrollP = Math.max(mMinScrollP, Math.min(mMaxScrollP, (mNumStackTasks - 2))
                        - Math.max(0, mUnfocusedRange.getAbsoluteX(initialTopNormX)));
            }
        }
    }

    /**
     * Creates task overrides to ensure the initial stack layout if necessary.
     */
    public void setTaskOverridesForInitialState(TaskStack stack, boolean ignoreScrollToFront) {
        RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();

        mTaskIndexOverrideMap.clear();

        boolean scrollToFront = launchState.launchedFromHome ||
                launchState.launchedFromBlacklistedApp ||
                launchState.launchedViaDockGesture;
        if (getInitialFocusState() == STATE_UNFOCUSED && mNumStackTasks > 1) {
            if (ignoreScrollToFront || (!launchState.launchedWithAltTab && !scrollToFront)) {
                // Set the initial scroll to the predefined state (which differs from the stack)
                float [] initialNormX = null;
                float minBottomTaskNormX = getNormalizedXFromUnfocusedY(mSystemInsets.bottom +
                        mInitialBottomOffset, FROM_BOTTOM);
                float maxBottomTaskNormX = getNormalizedXFromUnfocusedY(mFocusedTopPeekHeight +
                        mTaskRect.height() - mMinMargin, FROM_TOP);
                if (mNumStackTasks <= 2) {
                    // For small stacks, position the tasks so that they are top aligned to under
                    // the action button, but ensure that it is at least a certain offset from the
                    // bottom of the stack
                    initialNormX = new float[] {
                            Math.min(maxBottomTaskNormX, minBottomTaskNormX),
                            getNormalizedXFromUnfocusedY(mFocusedTopPeekHeight, FROM_TOP)
                    };
                } else {
                    initialNormX = new float[] {
                            minBottomTaskNormX,
                            getNormalizedXFromUnfocusedY(mInitialTopOffset, FROM_TOP)
                    };
                }

                mUnfocusedRange.offset(0f);
                List<Task> tasks = stack.getStackTasks();
                int taskCount = tasks.size();
                for (int i = taskCount - 1; i >= 0; i--) {
                    int indexFromFront = taskCount - i - 1;
                    if (indexFromFront >= initialNormX.length) {
                        break;
                    }
                    float newTaskProgress = mInitialScrollP +
                            mUnfocusedRange.getAbsoluteX(initialNormX[indexFromFront]);
                    mTaskIndexOverrideMap.put(tasks.get(i).key.id, newTaskProgress);
                }
            }
        }
    }

    /**
     * Adds and override task progress for the given task when transitioning from focused to
     * unfocused state.
     */
    public void addUnfocusedTaskOverride(Task task, float stackScroll) {
        if (mFocusState != STATE_UNFOCUSED) {
            mFocusedRange.offset(stackScroll);
            mUnfocusedRange.offset(stackScroll);
            float focusedRangeX = mFocusedRange.getNormalizedX(mTaskIndexMap.get(task.key.id));
            float focusedY = mFocusedCurveInterpolator.getInterpolation(focusedRangeX);
            float unfocusedRangeX = mUnfocusedCurveInterpolator.getX(focusedY);
            float unfocusedTaskProgress = stackScroll + mUnfocusedRange.getAbsoluteX(unfocusedRangeX);
            if (Float.compare(focusedRangeX, unfocusedRangeX) != 0) {
                mTaskIndexOverrideMap.put(task.key.id, unfocusedTaskProgress);
            }
        }
    }

    /**
     * Adds and override task progress for the given task when transitioning from focused to
     * unfocused state.
     */
    public void addUnfocusedTaskOverride(TaskView taskView, float stackScroll) {
        mFocusedRange.offset(stackScroll);
        mUnfocusedRange.offset(stackScroll);

        Task task = taskView.getTask();
        int top = taskView.getTop() - mTaskRect.top;
        float focusedRangeX = getNormalizedXFromFocusedY(top, FROM_TOP);
        float unfocusedRangeX = getNormalizedXFromUnfocusedY(top, FROM_TOP);
        float unfocusedTaskProgress = stackScroll + mUnfocusedRange.getAbsoluteX(unfocusedRangeX);
        if (Float.compare(focusedRangeX, unfocusedRangeX) != 0) {
            mTaskIndexOverrideMap.put(task.key.id, unfocusedTaskProgress);
        }
    }

    public void clearUnfocusedTaskOverrides() {
        mTaskIndexOverrideMap.clear();
    }

    /**
     * Updates this stack when a scroll happens.
     *
     */
    public float updateFocusStateOnScroll(float lastTargetStackScroll, float targetStackScroll,
            float lastStackScroll) {
        if (targetStackScroll == lastStackScroll) {
            return targetStackScroll;
        }

        float deltaScroll = targetStackScroll - lastStackScroll;
        float deltaTargetScroll = targetStackScroll - lastTargetStackScroll;
        float newScroll = targetStackScroll;
        mUnfocusedRange.offset(targetStackScroll);
        for (int i = mTaskIndexOverrideMap.size() - 1; i >= 0; i--) {
            int taskId = mTaskIndexOverrideMap.keyAt(i);
            float x = mTaskIndexMap.get(taskId);
            float overrideX = mTaskIndexOverrideMap.get(taskId, 0f);
            float newOverrideX = overrideX + deltaScroll;
            if (isInvalidOverrideX(x, overrideX, newOverrideX)) {
                // Remove the override once we reach the original task index
                mTaskIndexOverrideMap.removeAt(i);
            } else if ((overrideX >= x && deltaScroll <= 0f) ||
                    (overrideX <= x && deltaScroll >= 0f)) {
                // Scrolling from override x towards x, then lock the task in place
                mTaskIndexOverrideMap.put(taskId, newOverrideX);
            } else {
                // Scrolling override x away from x, we should still move the scroll towards x
                newScroll = lastStackScroll;
                newOverrideX = overrideX - deltaTargetScroll;
                if (isInvalidOverrideX(x, overrideX, newOverrideX)) {
                    mTaskIndexOverrideMap.removeAt(i);
                } else{
                    mTaskIndexOverrideMap.put(taskId, newOverrideX);
                }
            }
        }
        return newScroll;
    }

    private boolean isInvalidOverrideX(float x, float overrideX, float newOverrideX) {
        boolean outOfBounds = mUnfocusedRange.getNormalizedX(newOverrideX) < 0f ||
                mUnfocusedRange.getNormalizedX(newOverrideX) > 1f;
        return outOfBounds || (overrideX >= x && x >= newOverrideX) ||
                (overrideX <= x && x <= newOverrideX);
    }

    /**
     * Returns the default focus state.
     */
    public int getInitialFocusState() {
        RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
        RecentsDebugFlags debugFlags = Recents.getDebugFlags();
        if (debugFlags.isPagingEnabled() || launchState.launchedWithAltTab) {
            return STATE_FOCUSED;
        } else {
            return STATE_UNFOCUSED;
        }
    }

    public Rect getStackActionButtonRect() {
        return useGridLayout()
                ? mTaskGridLayoutAlgorithm.getStackActionButtonRect() : mStackActionButtonRect;
    }

    /**
     * Returns the TaskViewTransform that would put the task just off the back of the stack.
     */
    public TaskViewTransform getBackOfStackTransform() {
        return mBackOfStackTransform;
    }

    /**
     * Returns the TaskViewTransform that would put the task just off the front of the stack.
     */
    public TaskViewTransform getFrontOfStackTransform() {
        return mFrontOfStackTransform;
    }

    /**
     * Returns the current stack state.
     */
    public StackState getStackState() {
        return mState;
    }

    /**
     * Returns whether this stack layout has been initialized.
     */
    public boolean isInitialized() {
        return !mStackRect.isEmpty();
    }

    /**
     * Computes the maximum number of visible tasks and thumbnails when the scroll is at the initial
     * stack scroll.  Requires that update() is called first.
     */
    public VisibilityReport computeStackVisibilityReport(ArrayList<Task> tasks) {
        // Ensure minimum visibility count
        if (tasks.size() <= 1) {
            return new VisibilityReport(1, 1);
        }

        // Quick return when there are no stack tasks
        if (mNumStackTasks == 0) {
            return new VisibilityReport(Math.max(mNumFreeformTasks, 1),
                    Math.max(mNumFreeformTasks, 1));
        }

        // Otherwise, walk backwards in the stack and count the number of tasks and visible
        // thumbnails and add that to the total freeform task count
        TaskViewTransform tmpTransform = new TaskViewTransform();
        Range currentRange = getInitialFocusState() > 0f ? mFocusedRange : mUnfocusedRange;
        currentRange.offset(mInitialScrollP);
        int taskBarHeight = mContext.getResources().getDimensionPixelSize(
                R.dimen.recents_task_view_header_height);
        int numVisibleTasks = Math.max(mNumFreeformTasks, 1);
        int numVisibleThumbnails = Math.max(mNumFreeformTasks, 1);
        float prevScreenY = Integer.MAX_VALUE;
        for (int i = tasks.size() - 1; i >= 0; i--) {
            Task task = tasks.get(i);

            // Skip freeform
            if (task.isFreeformTask()) {
                continue;
            }

            // Skip invisible
            float taskProgress = getStackScrollForTask(task);
            if (!currentRange.isInRange(taskProgress)) {
                continue;
            }

            boolean isFrontMostTaskInGroup = task.group == null || task.group.isFrontMostTask(task);
            if (isFrontMostTaskInGroup) {
                getStackTransform(taskProgress, taskProgress, mInitialScrollP, mFocusState,
                        tmpTransform, null, false /* ignoreSingleTaskCase */,
                        false /* forceUpdate */);
                float screenY = tmpTransform.rect.top;
                boolean hasVisibleThumbnail = (prevScreenY - screenY) > taskBarHeight;
                if (hasVisibleThumbnail) {
                    numVisibleThumbnails++;
                    numVisibleTasks++;
                    prevScreenY = screenY;
                } else {
                    // Once we hit the next front most task that does not have a visible thumbnail,
                    // walk through remaining visible set
                    for (int j = i; j >= 0; j--) {
                        numVisibleTasks++;
                        taskProgress = getStackScrollForTask(tasks.get(j));
                        if (!currentRange.isInRange(taskProgress)) {
                            continue;
                        }
                    }
                    break;
                }
            } else if (!isFrontMostTaskInGroup) {
                // Affiliated task, no thumbnail
                numVisibleTasks++;
            }
        }
        return new VisibilityReport(numVisibleTasks, numVisibleThumbnails);
    }

    /**
     * Returns the transform for the given task.  This transform is relative to the mTaskRect, which
     * is what the view is measured and laid out with.
     */
    public TaskViewTransform getStackTransform(Task task, float stackScroll,
            TaskViewTransform transformOut, TaskViewTransform frontTransform) {
        return getStackTransform(task, stackScroll, mFocusState, transformOut, frontTransform,
                false /* forceUpdate */, false /* ignoreTaskOverrides */);
    }

    public TaskViewTransform getStackTransform(Task task, float stackScroll,
            TaskViewTransform transformOut, TaskViewTransform frontTransform,
            boolean ignoreTaskOverrides) {
        return getStackTransform(task, stackScroll, mFocusState, transformOut, frontTransform,
                false /* forceUpdate */, ignoreTaskOverrides);
    }

    public TaskViewTransform getStackTransform(Task task, float stackScroll, int focusState,
            TaskViewTransform transformOut, TaskViewTransform frontTransform, boolean forceUpdate,
            boolean ignoreTaskOverrides) {
        if (mFreeformLayoutAlgorithm.isTransformAvailable(task, this)) {
            mFreeformLayoutAlgorithm.getTransform(task, transformOut, this);
            return transformOut;
        } else if (useGridLayout()) {
            int taskIndex = mTaskIndexMap.get(task.key.id);
            int taskCount = mTaskIndexMap.size();
            mTaskGridLayoutAlgorithm.getTransform(taskIndex, taskCount, transformOut, this);
            return transformOut;
        } else {
            // Return early if we have an invalid index
            int nonOverrideTaskProgress = mTaskIndexMap.get(task.key.id, -1);
            if (task == null || nonOverrideTaskProgress == -1) {
                transformOut.reset();
                return transformOut;
            }
            float taskProgress = ignoreTaskOverrides
                    ? nonOverrideTaskProgress
                    : getStackScrollForTask(task);
            getStackTransform(taskProgress, nonOverrideTaskProgress, stackScroll, focusState,
                    transformOut, frontTransform, false /* ignoreSingleTaskCase */, forceUpdate);
            return transformOut;
        }
    }

    /**
     * Like {@link #getStackTransform}, but in screen coordinates
     */
    public TaskViewTransform getStackTransformScreenCoordinates(Task task, float stackScroll,
            TaskViewTransform transformOut, TaskViewTransform frontTransform,
            Rect windowOverrideRect) {
        TaskViewTransform transform = getStackTransform(task, stackScroll, mFocusState,
                transformOut, frontTransform, true /* forceUpdate */,
                false /* ignoreTaskOverrides */);
        return transformToScreenCoordinates(transform, windowOverrideRect);
    }

    /**
     * Transforms the given {@param transformOut} to the screen coordinates, overriding the current
     * window rectangle with {@param windowOverrideRect} if non-null.
     */
    public TaskViewTransform transformToScreenCoordinates(TaskViewTransform transformOut,
            Rect windowOverrideRect) {
        Rect windowRect = windowOverrideRect != null
                ? windowOverrideRect
                : Recents.getSystemServices().getWindowRect();
        transformOut.rect.offset(windowRect.left, windowRect.top);
        return transformOut;
    }

    /**
     * Update/get the transform.
     *
     * @param ignoreSingleTaskCase When set, will ensure that the transform computed does not take
     *                             into account the special single-task case.  This is only used
     *                             internally to ensure that we can calculate the transform for any
     *                             position in the stack.
     */
    public void getStackTransform(float taskProgress, float nonOverrideTaskProgress,
            float stackScroll, int focusState, TaskViewTransform transformOut,
            TaskViewTransform frontTransform, boolean ignoreSingleTaskCase, boolean forceUpdate) {
        SystemServicesProxy ssp = Recents.getSystemServices();

        // Ensure that the task is in range
        mUnfocusedRange.offset(stackScroll);
        mFocusedRange.offset(stackScroll);
        boolean unfocusedVisible = mUnfocusedRange.isInRange(taskProgress);
        boolean focusedVisible = mFocusedRange.isInRange(taskProgress);

        // Skip if the task is not visible
        if (!forceUpdate && !unfocusedVisible && !focusedVisible) {
            transformOut.reset();
            return;
        }

        // Map the absolute task progress to the normalized x at the stack scroll.  We use this to
        // calculate positions along the curve.
        mUnfocusedRange.offset(stackScroll);
        mFocusedRange.offset(stackScroll);
        float unfocusedRangeX = mUnfocusedRange.getNormalizedX(taskProgress);
        float focusedRangeX = mFocusedRange.getNormalizedX(taskProgress);

        // Map the absolute task progress to the normalized x at the bounded stack scroll.  We use
        // this to calculate bounded properties, like translationZ and outline alpha.
        float boundedStackScroll = Utilities.clamp(stackScroll, mMinScrollP, mMaxScrollP);
        mUnfocusedRange.offset(boundedStackScroll);
        mFocusedRange.offset(boundedStackScroll);
        float boundedScrollUnfocusedRangeX = mUnfocusedRange.getNormalizedX(taskProgress);
        float boundedScrollUnfocusedNonOverrideRangeX =
                mUnfocusedRange.getNormalizedX(nonOverrideTaskProgress);

        // Map the absolute task progress to the normalized x at the upper bounded stack scroll.
        // We use this to calculate the dim, which is bounded only on one end.
        float lowerBoundedStackScroll = Utilities.clamp(stackScroll, -Float.MAX_VALUE, mMaxScrollP);
        mUnfocusedRange.offset(lowerBoundedStackScroll);
        mFocusedRange.offset(lowerBoundedStackScroll);
        float lowerBoundedUnfocusedRangeX = mUnfocusedRange.getNormalizedX(taskProgress);
        float lowerBoundedFocusedRangeX = mFocusedRange.getNormalizedX(taskProgress);

        int x = (mStackRect.width() - mTaskRect.width()) / 2;
        int y;
        float z;
        float dimAlpha;
        float viewOutlineAlpha;
        if (!ssp.hasFreeformWorkspaceSupport() && mNumStackTasks == 1 && !ignoreSingleTaskCase) {
            // When there is exactly one task, then decouple the task from the stack and just move
            // in screen space
            float tmpP = (mMinScrollP - stackScroll) / mNumStackTasks;
            int centerYOffset = (mStackRect.top - mTaskRect.top) +
                    (mStackRect.height() - mSystemInsets.bottom - mTaskRect.height()) / 2;
            y = centerYOffset + getYForDeltaP(tmpP, 0);
            z = mMaxTranslationZ;
            dimAlpha = 0f;
            viewOutlineAlpha = OUTLINE_ALPHA_MIN_VALUE +
                    (OUTLINE_ALPHA_MAX_VALUE - OUTLINE_ALPHA_MIN_VALUE) / 2f;

        } else {
            // Otherwise, update the task to the stack layout
            int unfocusedY = (int) ((1f - mUnfocusedCurveInterpolator.getInterpolation(
                    unfocusedRangeX)) * mStackRect.height());
            int focusedY = (int) ((1f - mFocusedCurveInterpolator.getInterpolation(
                    focusedRangeX)) * mStackRect.height());
            float unfocusedDim = mUnfocusedDimCurveInterpolator.getInterpolation(
                    lowerBoundedUnfocusedRangeX);
            float focusedDim = mFocusedDimCurveInterpolator.getInterpolation(
                    lowerBoundedFocusedRangeX);

            // Special case, because we override the initial task positions differently for small
            // stacks, we clamp the dim to 0 in the initial position, and then only modulate the
            // dim when the task is scrolled back towards the top of the screen
            if (mNumStackTasks <= 2 && nonOverrideTaskProgress == 0f) {
                if (boundedScrollUnfocusedRangeX >= 0.5f) {
                    unfocusedDim = 0f;
                } else {
                    float offset = mUnfocusedDimCurveInterpolator.getInterpolation(0.5f);
                    unfocusedDim -= offset;
                    unfocusedDim *= MAX_DIM / (MAX_DIM - offset);
                }
            }

            y = (mStackRect.top - mTaskRect.top) +
                    (int) Utilities.mapRange(focusState, unfocusedY, focusedY);
            z = Utilities.mapRange(Utilities.clamp01(boundedScrollUnfocusedNonOverrideRangeX),
                    mMinTranslationZ, mMaxTranslationZ);
            dimAlpha = Utilities.mapRange(focusState, unfocusedDim, focusedDim);
            viewOutlineAlpha = Utilities.mapRange(Utilities.clamp01(boundedScrollUnfocusedRangeX),
                    OUTLINE_ALPHA_MIN_VALUE, OUTLINE_ALPHA_MAX_VALUE);
        }

        // Fill out the transform
        transformOut.scale = 1f;
        transformOut.alpha = 1f;
        transformOut.translationZ = z;
        transformOut.dimAlpha = dimAlpha;
        transformOut.viewOutlineAlpha = viewOutlineAlpha;
        transformOut.rect.set(mTaskRect);
        transformOut.rect.offset(x, y);
        Utilities.scaleRectAboutCenter(transformOut.rect, transformOut.scale);
        transformOut.visible = (transformOut.rect.top < mStackRect.bottom) &&
                (frontTransform == null || transformOut.rect.top != frontTransform.rect.top);
    }

    /**
     * Returns the untransformed task view bounds.
     */
    public Rect getUntransformedTaskViewBounds() {
        return new Rect(mTaskRect);
    }

    /**
     * Returns the scroll progress to scroll to such that the top of the task is at the top of the
     * stack.
     */
    float getStackScrollForTask(Task t) {
        Float overrideP = mTaskIndexOverrideMap.get(t.key.id, null);
        if (overrideP == null) {
            return (float) mTaskIndexMap.get(t.key.id, 0);
        }
        return overrideP;
    }

    /**
     * Returns the original scroll progress to scroll to such that the top of the task is at the top
     * of the stack.
     */
    float getStackScrollForTaskIgnoreOverrides(Task t) {
        return (float) mTaskIndexMap.get(t.key.id, 0);
    }

    /**
     * Returns the scroll progress to scroll to such that the top of the task at the initial top
     * offset (which is at the task's brightest point).
     */
    float getStackScrollForTaskAtInitialOffset(Task t) {
        float normX = getNormalizedXFromUnfocusedY(mInitialTopOffset, FROM_TOP);
        mUnfocusedRange.offset(0f);
        return Utilities.clamp((float) mTaskIndexMap.get(t.key.id, 0) - Math.max(0,
                mUnfocusedRange.getAbsoluteX(normX)), mMinScrollP, mMaxScrollP);
    }

    /**
     * Maps a movement in screen y, relative to {@param downY}, to a movement in along the arc
     * length of the curve.  We know the curve is mostly flat, so we just map the length of the
     * screen along the arc-length proportionally (1/arclength).
     */
    public float getDeltaPForY(int downY, int y) {
        float deltaP = (float) (y - downY) / mStackRect.height() *
                mUnfocusedCurveInterpolator.getArcLength();
        return -deltaP;
    }

    /**
     * This is the inverse of {@link #getDeltaPForY}.  Given a movement along the arc length
     * of the curve, map back to the screen y.
     */
    public int getYForDeltaP(float downScrollP, float p) {
        int y = (int) ((p - downScrollP) * mStackRect.height() *
                (1f / mUnfocusedCurveInterpolator.getArcLength()));
        return -y;
    }

    /**
     * Returns the task stack bounds in the current orientation.  This rect takes into account the
     * top and right system insets (but not the bottom inset) and left/right paddings, but _not_
     * the top/bottom padding or insets.
     */
    public void getTaskStackBounds(Rect displayRect, Rect windowRect, int topInset, int leftInset,
            int rightInset, Rect taskStackBounds) {
        taskStackBounds.set(windowRect.left + leftInset, windowRect.top + topInset,
                windowRect.right - rightInset, windowRect.bottom);

        // Ensure that the new width is at most the smaller display edge size
        int sideMargin = getScaleForExtent(windowRect, displayRect, mBaseSideMargin, mMinMargin,
                WIDTH);
        int targetStackWidth = taskStackBounds.width() - 2 * sideMargin;
        if (Utilities.getAppConfiguration(mContext).orientation
                == Configuration.ORIENTATION_LANDSCAPE) {
            // If we are in landscape, calculate the width of the stack in portrait and ensure that
            // we are not larger than that size
            Rect portraitDisplayRect = new Rect(0, 0,
                    Math.min(displayRect.width(), displayRect.height()),
                    Math.max(displayRect.width(), displayRect.height()));
            int portraitSideMargin = getScaleForExtent(portraitDisplayRect, portraitDisplayRect,
                    mBaseSideMargin, mMinMargin, WIDTH);
            targetStackWidth = Math.min(targetStackWidth,
                    portraitDisplayRect.width() - 2 * portraitSideMargin);
        }
        taskStackBounds.inset((taskStackBounds.width() - targetStackWidth) / 2, 0);
    }

    /**
     * Retrieves resources that are constant regardless of the current configuration of the device.
     */
    public static int getDimensionForDevice(Context ctx, int phoneResId,
            int tabletResId, int xlargeTabletResId, int gridLayoutResId) {
        return getDimensionForDevice(ctx, phoneResId, phoneResId, tabletResId, tabletResId,
                xlargeTabletResId, xlargeTabletResId, gridLayoutResId);
    }

    /**
     * Retrieves resources that are constant regardless of the current configuration of the device.
     */
    public static int getDimensionForDevice(Context ctx, int phonePortResId, int phoneLandResId,
            int tabletPortResId, int tabletLandResId, int xlargeTabletPortResId,
            int xlargeTabletLandResId, int gridLayoutResId) {
        RecentsConfiguration config = Recents.getConfiguration();
        Resources res = ctx.getResources();
        boolean isLandscape = Utilities.getAppConfiguration(ctx).orientation ==
                Configuration.ORIENTATION_LANDSCAPE;
        if (config.isGridEnabled) {
            return res.getDimensionPixelSize(gridLayoutResId);
        } else if (config.isXLargeScreen) {
            return res.getDimensionPixelSize(isLandscape
                    ? xlargeTabletLandResId
                    : xlargeTabletPortResId);
        } else if (config.isLargeScreen) {
            return res.getDimensionPixelSize(isLandscape
                    ? tabletLandResId
                    : tabletPortResId);
        } else {
            return res.getDimensionPixelSize(isLandscape
                    ? phoneLandResId
                    : phonePortResId);
        }
    }

    /**
     * Returns the normalized x on the unfocused curve given an absolute Y position (relative to the
     * stack height).
     */
    private float getNormalizedXFromUnfocusedY(float y, @AnchorSide int fromSide) {
        float offset = (fromSide == FROM_TOP)
                ? mStackRect.height() - y
                : y;
        float offsetPct = offset / mStackRect.height();
        return mUnfocusedCurveInterpolator.getX(offsetPct);
    }

    /**
     * Returns the normalized x on the focused curve given an absolute Y position (relative to the
     * stack height).
     */
    private float getNormalizedXFromFocusedY(float y, @AnchorSide int fromSide) {
        float offset = (fromSide == FROM_TOP)
                ? mStackRect.height() - y
                : y;
        float offsetPct = offset / mStackRect.height();
        return mFocusedCurveInterpolator.getX(offsetPct);
    }

    /**
     * Creates a new path for the focused curve.
     */
    private Path constructFocusedCurve() {
        // Initialize the focused curve. This curve is a piecewise curve composed of several
        // linear pieces that goes from (0,1) through (0.5, peek height offset),
        // (0.5, bottom task offsets), and (1,0).
        float topPeekHeightPct = (float) mFocusedTopPeekHeight / mStackRect.height();
        float bottomPeekHeightPct = (float) (mStackBottomOffset + mFocusedBottomPeekHeight) /
                mStackRect.height();
        float minBottomPeekHeightPct = (float) (mFocusedTopPeekHeight + mTaskRect.height() -
                mMinMargin) / mStackRect.height();
        Path p = new Path();
        p.moveTo(0f, 1f);
        p.lineTo(0.5f, 1f - topPeekHeightPct);
        p.lineTo(1f - (0.5f / mFocusedRange.relativeMax), Math.max(1f - minBottomPeekHeightPct,
                bottomPeekHeightPct));
        p.lineTo(1f, 0f);
        return p;
    }

    /**
     * Creates a new path for the unfocused curve.
     */
    private Path constructUnfocusedCurve() {
        // Initialize the unfocused curve. This curve is a piecewise curve composed of two quadradic
        // beziers that goes from (0,1) through (0.5, peek height offset) and ends at (1,0).  This
        // ensures that we match the range, at which 0.5 represents the stack scroll at the current
        // task progress.  Because the height offset can change depending on a resource, we compute
        // the control point of the second bezier such that between it and a first known point,
        // there is a tangent at (0.5, peek height offset).
        float cpoint1X = 0.4f;
        float cpoint1Y = 0.975f;
        float topPeekHeightPct = (float) mFocusedTopPeekHeight / mStackRect.height();
        float slope = ((1f - topPeekHeightPct) - cpoint1Y) / (0.5f - cpoint1X);
        float b = 1f - slope * cpoint1X;
        float cpoint2X = 0.65f;
        float cpoint2Y = slope * cpoint2X + b;
        Path p = new Path();
        p.moveTo(0f, 1f);
        p.cubicTo(0f, 1f, cpoint1X, cpoint1Y, 0.5f, 1f - topPeekHeightPct);
        p.cubicTo(0.5f, 1f - topPeekHeightPct, cpoint2X, cpoint2Y, 1f, 0f);
        return p;
    }

    /**
     * Creates a new path for the focused dim curve.
     */
    private Path constructFocusedDimCurve() {
        Path p = new Path();
        // The focused dim interpolator starts at max dim, reduces to zero at 0.5 (the focused
        // task), then goes back to max dim at the next task
        p.moveTo(0f, MAX_DIM);
        p.lineTo(0.5f, 0f);
        p.lineTo(0.5f + (0.5f / mFocusedRange.relativeMax), MAX_DIM);
        p.lineTo(1f, MAX_DIM);
        return p;
    }

    /**
     * Creates a new path for the unfocused dim curve.
     */
    private Path constructUnfocusedDimCurve() {
        float focusX = getNormalizedXFromUnfocusedY(mInitialTopOffset, FROM_TOP);
        float cpoint2X = focusX + (1f - focusX) / 2;
        Path p = new Path();
        // The unfocused dim interpolator starts at max dim, reduces to zero at 0.5 (the focused
        // task), then goes back to max dim towards the front of the stack
        p.moveTo(0f, MAX_DIM);
        p.cubicTo(focusX * 0.5f, MAX_DIM, focusX * 0.75f, MAX_DIM * 0.75f, focusX, 0f);
        p.cubicTo(cpoint2X, 0f, cpoint2X, MED_DIM, 1f, MED_DIM);
        return p;
    }

    /**
     * Scales the given {@param value} to the scale of the {@param instance} rect relative to the
     * {@param other} rect in the {@param extent} side.
     */
    private int getScaleForExtent(Rect instance, Rect other, int value, int minValue,
                                  @Extent int extent) {
        if (extent == WIDTH) {
            float scale = Utilities.clamp01((float) instance.width() / other.width());
            return Math.max(minValue, (int) (scale * value));
        } else if (extent == HEIGHT) {
            float scale = Utilities.clamp01((float) instance.height() / other.height());
            return Math.max(minValue, (int) (scale * value));
        }
        return value;
    }

    /**
     * Updates the current transforms that would put a TaskView at the front and back of the stack.
     */
    private void updateFrontBackTransforms() {
        // Return early if we have not yet initialized
        if (mStackRect.isEmpty()) {
            return;
        }

        float min = Utilities.mapRange(mFocusState, mUnfocusedRange.relativeMin,
                mFocusedRange.relativeMin);
        float max = Utilities.mapRange(mFocusState, mUnfocusedRange.relativeMax,
                mFocusedRange.relativeMax);
        getStackTransform(min, min, 0f, mFocusState, mBackOfStackTransform, null,
                true /* ignoreSingleTaskCase */, true /* forceUpdate */);
        getStackTransform(max, max, 0f, mFocusState, mFrontOfStackTransform, null,
                true /* ignoreSingleTaskCase */, true /* forceUpdate */);
        mBackOfStackTransform.visible = true;
        mFrontOfStackTransform.visible = true;
    }

    /**
     * Returns the proper task rectangle according to the current grid state.
     */
    public Rect getTaskRect() {
        return useGridLayout() ? mTaskGridLayoutAlgorithm.getTaskGridRect() : mTaskRect;
    }

    public void dump(String prefix, PrintWriter writer) {
        String innerPrefix = prefix + "  ";

        writer.print(prefix); writer.print(TAG);
        writer.write(" numStackTasks="); writer.print(mNumStackTasks);
        writer.println();

        writer.print(innerPrefix);
        writer.print("insets="); writer.print(Utilities.dumpRect(mSystemInsets));
        writer.print(" stack="); writer.print(Utilities.dumpRect(mStackRect));
        writer.print(" task="); writer.print(Utilities.dumpRect(mTaskRect));
        writer.print(" freeform="); writer.print(Utilities.dumpRect(mFreeformRect));
        writer.print(" actionButton="); writer.print(Utilities.dumpRect(mStackActionButtonRect));
        writer.println();

        writer.print(innerPrefix);
        writer.print("minScroll="); writer.print(mMinScrollP);
        writer.print(" maxScroll="); writer.print(mMaxScrollP);
        writer.print(" initialScroll="); writer.print(mInitialScrollP);
        writer.println();

        writer.print(innerPrefix);
        writer.print("focusState="); writer.print(mFocusState);
        writer.println();

        if (mTaskIndexOverrideMap.size() > 0) {
            for (int i = mTaskIndexOverrideMap.size() - 1; i >= 0; i--) {
                int taskId = mTaskIndexOverrideMap.keyAt(i);
                float x = mTaskIndexMap.get(taskId);
                float overrideX = mTaskIndexOverrideMap.get(taskId, 0f);

                writer.print(innerPrefix);
                writer.print("taskId= "); writer.print(taskId);
                writer.print(" x= "); writer.print(x);
                writer.print(" overrideX= "); writer.print(overrideX);
                writer.println();
            }
        }
    }
}