/*
 * 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.server.wm;

import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.util.TypedValue.COMPLEX_UNIT_DIP;

import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.PinnedStackControllerProto.DEFAULT_BOUNDS;
import static com.android.server.wm.PinnedStackControllerProto.MOVEMENT_BOUNDS;

import android.app.RemoteAction;
import android.content.pm.ParceledListSlice;
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Size;
import android.util.Slog;
import android.util.TypedValue;
import android.util.proto.ProtoOutputStream;
import android.view.DisplayInfo;
import android.view.Gravity;
import android.view.IPinnedStackController;
import android.view.IPinnedStackListener;

import com.android.internal.policy.PipSnapAlgorithm;
import com.android.server.UiThread;

import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;

/**
 * Holds the common state of the pinned stack between the system and SystemUI. If SystemUI ever
 * needs to be restarted, it will be notified with the last known state.
 *
 * Changes to the pinned stack also flow through this controller, and generally, the system only
 * changes the pinned stack bounds through this controller in two ways:
 *
 * 1) When first entering PiP: the controller returns the valid bounds given, taking aspect ratio
 *    and IME state into account.
 * 2) When rotating the device: the controller calculates the new bounds in the new orientation,
 *    taking the minimized and IME state into account. In this case, we currently ignore the
 *    SystemUI adjustments (ie. expanded for menu, interaction, etc).
 *
 * Other changes in the system, including adjustment of IME, configuration change, and more are
 * handled by SystemUI (similar to the docked stack divider).
 */
class PinnedStackController {

    private static final String TAG = TAG_WITH_CLASS_NAME ? "PinnedStackController" : TAG_WM;

    public static final float INVALID_SNAP_FRACTION = -1f;
    private final WindowManagerService mService;
    private final DisplayContent mDisplayContent;
    private final Handler mHandler = UiThread.getHandler();

    private IPinnedStackListener mPinnedStackListener;
    private final PinnedStackListenerDeathHandler mPinnedStackListenerDeathHandler =
            new PinnedStackListenerDeathHandler();

    private final PinnedStackControllerCallback mCallbacks = new PinnedStackControllerCallback();
    private final PipSnapAlgorithm mSnapAlgorithm;

    // States that affect how the PIP can be manipulated
    private boolean mIsMinimized;
    private boolean mIsImeShowing;
    private int mImeHeight;
    private boolean mIsShelfShowing;
    private int mShelfHeight;

    // The set of actions and aspect-ratio for the that are currently allowed on the PiP activity
    private ArrayList<RemoteAction> mActions = new ArrayList<>();
    private float mAspectRatio = -1f;

    // Used to calculate stack bounds across rotations
    private final DisplayInfo mDisplayInfo = new DisplayInfo();
    private final Rect mStableInsets = new Rect();

    // The size and position information that describes where the pinned stack will go by default.
    private int mDefaultMinSize;
    private int mDefaultStackGravity;
    private float mDefaultAspectRatio;
    private Point mScreenEdgeInsets;
    private int mCurrentMinSize;
    private float mReentrySnapFraction = INVALID_SNAP_FRACTION;
    private WeakReference<AppWindowToken> mLastPipActivity = null;

    // The aspect ratio bounds of the PIP.
    private float mMinAspectRatio;
    private float mMaxAspectRatio;

    // Temp vars for calculation
    private final DisplayMetrics mTmpMetrics = new DisplayMetrics();
    private final Rect mTmpInsets = new Rect();
    private final Rect mTmpRect = new Rect();
    private final Rect mTmpAnimatingBoundsRect = new Rect();
    private final Point mTmpDisplaySize = new Point();


    /**
     * The callback object passed to listeners for them to notify the controller of state changes.
     */
    private class PinnedStackControllerCallback extends IPinnedStackController.Stub {

        @Override
        public void setIsMinimized(final boolean isMinimized) {
            mHandler.post(() -> {
                mIsMinimized = isMinimized;
                mSnapAlgorithm.setMinimized(isMinimized);
            });
        }

        @Override
        public void setMinEdgeSize(int minEdgeSize) {
            mHandler.post(() -> {
                mCurrentMinSize = Math.max(mDefaultMinSize, minEdgeSize);
            });
        }

        @Override
        public int getDisplayRotation() {
            synchronized (mService.mWindowMap) {
                return mDisplayInfo.rotation;
            }
        }
    }

    /**
     * Handler for the case where the listener dies.
     */
    private class PinnedStackListenerDeathHandler implements IBinder.DeathRecipient {

        @Override
        public void binderDied() {
            // Clean up the state if the listener dies
            if (mPinnedStackListener != null) {
                mPinnedStackListener.asBinder().unlinkToDeath(mPinnedStackListenerDeathHandler, 0);
            }
            mPinnedStackListener = null;
        }
    }

    PinnedStackController(WindowManagerService service, DisplayContent displayContent) {
        mService = service;
        mDisplayContent = displayContent;
        mSnapAlgorithm = new PipSnapAlgorithm(service.mContext);
        mDisplayInfo.copyFrom(mDisplayContent.getDisplayInfo());
        reloadResources();
        // Initialize the aspect ratio to the default aspect ratio.  Don't do this in reload
        // resources as it would clobber mAspectRatio when entering PiP from fullscreen which
        // triggers a configuration change and the resources to be reloaded.
        mAspectRatio = mDefaultAspectRatio;
    }

    void onConfigurationChanged() {
        reloadResources();
    }

    /**
     * Reloads all the resources for the current configuration.
     */
    private void reloadResources() {
        final Resources res = mService.mContext.getResources();
        mDefaultMinSize = res.getDimensionPixelSize(
                com.android.internal.R.dimen.default_minimal_size_pip_resizable_task);
        mCurrentMinSize = mDefaultMinSize;
        mDefaultAspectRatio = res.getFloat(
                com.android.internal.R.dimen.config_pictureInPictureDefaultAspectRatio);
        final String screenEdgeInsetsDpString = res.getString(
                com.android.internal.R.string.config_defaultPictureInPictureScreenEdgeInsets);
        final Size screenEdgeInsetsDp = !screenEdgeInsetsDpString.isEmpty()
                ? Size.parseSize(screenEdgeInsetsDpString)
                : null;
        mDefaultStackGravity = res.getInteger(
                com.android.internal.R.integer.config_defaultPictureInPictureGravity);
        mDisplayContent.getDisplay().getRealMetrics(mTmpMetrics);
        mScreenEdgeInsets = screenEdgeInsetsDp == null ? new Point()
                : new Point(dpToPx(screenEdgeInsetsDp.getWidth(), mTmpMetrics),
                        dpToPx(screenEdgeInsetsDp.getHeight(), mTmpMetrics));
        mMinAspectRatio = res.getFloat(
                com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio);
        mMaxAspectRatio = res.getFloat(
                com.android.internal.R.dimen.config_pictureInPictureMaxAspectRatio);
    }

    /**
     * Registers a pinned stack listener.
     */
    void registerPinnedStackListener(IPinnedStackListener listener) {
        try {
            listener.asBinder().linkToDeath(mPinnedStackListenerDeathHandler, 0);
            listener.onListenerRegistered(mCallbacks);
            mPinnedStackListener = listener;
            notifyImeVisibilityChanged(mIsImeShowing, mImeHeight);
            notifyShelfVisibilityChanged(mIsShelfShowing, mShelfHeight);
            // The movement bounds notification needs to be sent before the minimized state, since
            // SystemUI may use the bounds to retore the minimized position
            notifyMovementBoundsChanged(false /* fromImeAdjustment */,
                    false /* fromShelfAdjustment */);
            notifyActionsChanged(mActions);
            notifyMinimizeChanged(mIsMinimized);
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to register pinned stack listener", e);
        }
    }

    /**
     * @return whether the given {@param aspectRatio} is valid.
     */
    public boolean isValidPictureInPictureAspectRatio(float aspectRatio) {
        return Float.compare(mMinAspectRatio, aspectRatio) <= 0 &&
                Float.compare(aspectRatio, mMaxAspectRatio) <= 0;
    }

    /**
     * Returns the current bounds (or the default bounds if there are no current bounds) with the
     * specified aspect ratio.
     */
    Rect transformBoundsToAspectRatio(Rect stackBounds, float aspectRatio,
            boolean useCurrentMinEdgeSize) {
        // Save the snap fraction, calculate the aspect ratio based on screen size
        final float snapFraction = mSnapAlgorithm.getSnapFraction(stackBounds,
                getMovementBounds(stackBounds));

        final int minEdgeSize = useCurrentMinEdgeSize ? mCurrentMinSize : mDefaultMinSize;
        final Size size = mSnapAlgorithm.getSizeForAspectRatio(aspectRatio, minEdgeSize,
                mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
        final int left = (int) (stackBounds.centerX() - size.getWidth() / 2f);
        final int top = (int) (stackBounds.centerY() - size.getHeight() / 2f);
        stackBounds.set(left, top, left + size.getWidth(), top + size.getHeight());
        mSnapAlgorithm.applySnapFraction(stackBounds, getMovementBounds(stackBounds), snapFraction);
        if (mIsMinimized) {
            applyMinimizedOffset(stackBounds, getMovementBounds(stackBounds));
        }
        return stackBounds;
    }

    /**
     * Saves the current snap fraction for re-entry of the current activity into PiP.
     */
    void saveReentrySnapFraction(final AppWindowToken token, final Rect stackBounds) {
        mReentrySnapFraction = getSnapFraction(stackBounds);
        mLastPipActivity = new WeakReference<>(token);
    }

    /**
     * Resets the last saved snap fraction so that the default bounds will be returned.
     */
    void resetReentrySnapFraction(AppWindowToken token) {
        if (mLastPipActivity != null && mLastPipActivity.get() == token) {
            mReentrySnapFraction = INVALID_SNAP_FRACTION;
            mLastPipActivity = null;
        }
    }

    /**
     * @return the default bounds to show the PIP when there is no active PIP.
     */
    Rect getDefaultOrLastSavedBounds() {
        return getDefaultBounds(mReentrySnapFraction);
    }

    /**
     * @return the default bounds to show the PIP, if a {@param snapFraction} is provided, then it
     * will apply the default bounds to the provided snap fraction.
     */
    Rect getDefaultBounds(float snapFraction) {
        synchronized (mService.mWindowMap) {
            final Rect insetBounds = new Rect();
            getInsetBounds(insetBounds);

            final Rect defaultBounds = new Rect();
            final Size size = mSnapAlgorithm.getSizeForAspectRatio(mDefaultAspectRatio,
                    mDefaultMinSize, mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
            if (snapFraction != INVALID_SNAP_FRACTION) {
                defaultBounds.set(0, 0, size.getWidth(), size.getHeight());
                final Rect movementBounds = getMovementBounds(defaultBounds);
                mSnapAlgorithm.applySnapFraction(defaultBounds, movementBounds, snapFraction);
            } else {
                Gravity.apply(mDefaultStackGravity, size.getWidth(), size.getHeight(), insetBounds,
                        0, Math.max(mIsImeShowing ? mImeHeight : 0,
                                mIsShelfShowing ? mShelfHeight : 0),
                        defaultBounds);
            }
            return defaultBounds;
        }
    }

    /**
     * In the case where the display rotation is changed but there is no stack, we can't depend on
     * onTaskStackBoundsChanged() to be called.  But we still should update our known display info
     * with the new state so that we can update SystemUI.
     */
    synchronized void onDisplayInfoChanged() {
        mDisplayInfo.copyFrom(mDisplayContent.getDisplayInfo());
        notifyMovementBoundsChanged(false /* fromImeAdjustment */, false /* fromShelfAdjustment */);
    }

    /**
     * Updates the display info, calculating and returning the new stack and movement bounds in the
     * new orientation of the device if necessary.
     */
    boolean onTaskStackBoundsChanged(Rect targetBounds, Rect outBounds) {
        synchronized (mService.mWindowMap) {
            final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
            if (mDisplayInfo.equals(displayInfo)) {
                // We are already in the right orientation, ignore
                outBounds.setEmpty();
                return false;
            } else if (targetBounds.isEmpty()) {
                // The stack is null, we are just initializing the stack, so just store the display
                // info and ignore
                mDisplayInfo.copyFrom(displayInfo);
                outBounds.setEmpty();
                return false;
            }

            mTmpRect.set(targetBounds);
            final Rect postChangeStackBounds = mTmpRect;

            // Calculate the snap fraction of the current stack along the old movement bounds
            final float snapFraction = getSnapFraction(postChangeStackBounds);
            mDisplayInfo.copyFrom(displayInfo);

            // Calculate the stack bounds in the new orientation to the same same fraction along the
            // rotated movement bounds.
            final Rect postChangeMovementBounds = getMovementBounds(postChangeStackBounds,
                    false /* adjustForIme */, false /* adjustForShelf */);
            mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds,
                    snapFraction);
            if (mIsMinimized) {
                applyMinimizedOffset(postChangeStackBounds, postChangeMovementBounds);
            }

            notifyMovementBoundsChanged(false /* fromImeAdjustment */,
                    false /* fromShelfAdjustment */);

            outBounds.set(postChangeStackBounds);
            return true;
        }
    }

    /**
     * Sets the Ime state and height.
     */
    void setAdjustedForIme(boolean adjustedForIme, int imeHeight) {
        // Due to the order of callbacks from the system, we may receive an ime height even when
        // {@param adjustedForIme} is false, and also a zero height when {@param adjustedForIme}
        // is true.  Instead, ensure that the ime state changes with the height and if the ime is
        // showing, then the height is non-zero.
        final boolean imeShowing = adjustedForIme && imeHeight > 0;
        imeHeight = imeShowing ? imeHeight : 0;
        if (imeShowing == mIsImeShowing && imeHeight == mImeHeight) {
            return;
        }

        mIsImeShowing = imeShowing;
        mImeHeight = imeHeight;
        notifyImeVisibilityChanged(imeShowing, imeHeight);
        notifyMovementBoundsChanged(true /* fromImeAdjustment */, false /* fromShelfAdjustment */);
    }

    /**
     * Sets the shelf state and height.
     */
    void setAdjustedForShelf(boolean adjustedForShelf, int shelfHeight) {
        final boolean shelfShowing = adjustedForShelf && shelfHeight > 0;
        if (shelfShowing == mIsShelfShowing && shelfHeight == mShelfHeight) {
            return;
        }

        mIsShelfShowing = shelfShowing;
        mShelfHeight = shelfHeight;
        notifyShelfVisibilityChanged(shelfShowing, shelfHeight);
        notifyMovementBoundsChanged(false /* fromImeAdjustment */, true /* fromShelfAdjustment */);
    }

    /**
     * Sets the current aspect ratio.
     */
    void setAspectRatio(float aspectRatio) {
        if (Float.compare(mAspectRatio, aspectRatio) != 0) {
            mAspectRatio = aspectRatio;
            notifyMovementBoundsChanged(false /* fromImeAdjustment */,
                    false /* fromShelfAdjustment */);
        }
    }

    /**
     * @return the current aspect ratio.
     */
    float getAspectRatio() {
        return mAspectRatio;
    }

    /**
     * Sets the current set of actions.
     */
    void setActions(List<RemoteAction> actions) {
        mActions.clear();
        if (actions != null) {
            mActions.addAll(actions);
        }
        notifyActionsChanged(mActions);
    }

    /**
     * Notifies listeners that the PIP needs to be adjusted for the IME.
     */
    private void notifyImeVisibilityChanged(boolean imeVisible, int imeHeight) {
        if (mPinnedStackListener != null) {
            try {
                mPinnedStackListener.onImeVisibilityChanged(imeVisible, imeHeight);
            } catch (RemoteException e) {
                Slog.e(TAG_WM, "Error delivering bounds changed event.", e);
            }
        }
    }

    private void notifyShelfVisibilityChanged(boolean shelfVisible, int shelfHeight) {
        if (mPinnedStackListener != null) {
            try {
                mPinnedStackListener.onShelfVisibilityChanged(shelfVisible, shelfHeight);
            } catch (RemoteException e) {
                Slog.e(TAG_WM, "Error delivering bounds changed event.", e);
            }
        }
    }

    /**
     * Notifies listeners that the PIP minimized state has changed.
     */
    private void notifyMinimizeChanged(boolean isMinimized) {
        if (mPinnedStackListener != null) {
            try {
                mPinnedStackListener.onMinimizedStateChanged(isMinimized);
            } catch (RemoteException e) {
                Slog.e(TAG_WM, "Error delivering minimize changed event.", e);
            }
        }
    }

    /**
     * Notifies listeners that the PIP actions have changed.
     */
    private void notifyActionsChanged(List<RemoteAction> actions) {
        if (mPinnedStackListener != null) {
            try {
                mPinnedStackListener.onActionsChanged(new ParceledListSlice(actions));
            } catch (RemoteException e) {
                Slog.e(TAG_WM, "Error delivering actions changed event.", e);
            }
        }
    }

    /**
     * Notifies listeners that the PIP movement bounds have changed.
     */
    private void notifyMovementBoundsChanged(boolean fromImeAdjustment,
            boolean fromShelfAdjustment) {
        synchronized (mService.mWindowMap) {
            if (mPinnedStackListener == null) {
                return;
            }
            try {
                final Rect insetBounds = new Rect();
                getInsetBounds(insetBounds);
                final Rect normalBounds = getDefaultBounds(INVALID_SNAP_FRACTION);
                if (isValidPictureInPictureAspectRatio(mAspectRatio)) {
                    transformBoundsToAspectRatio(normalBounds, mAspectRatio,
                            false /* useCurrentMinEdgeSize */);
                }
                final Rect animatingBounds = mTmpAnimatingBoundsRect;
                final TaskStack pinnedStack = mDisplayContent.getPinnedStack();
                if (pinnedStack != null) {
                    pinnedStack.getAnimationOrCurrentBounds(animatingBounds);
                } else {
                    animatingBounds.set(normalBounds);
                }
                mPinnedStackListener.onMovementBoundsChanged(insetBounds, normalBounds,
                        animatingBounds, fromImeAdjustment, fromShelfAdjustment,
                        mDisplayInfo.rotation);
            } catch (RemoteException e) {
                Slog.e(TAG_WM, "Error delivering actions changed event.", e);
            }
        }
    }

    /**
     * @return the bounds on the screen that the PIP can be visible in.
     */
    private void getInsetBounds(Rect outRect) {
        synchronized (mService.mWindowMap) {
            mService.mPolicy.getStableInsetsLw(mDisplayInfo.rotation, mDisplayInfo.logicalWidth,
                    mDisplayInfo.logicalHeight, mDisplayInfo.displayCutout, mTmpInsets);
            outRect.set(mTmpInsets.left + mScreenEdgeInsets.x, mTmpInsets.top + mScreenEdgeInsets.y,
                    mDisplayInfo.logicalWidth - mTmpInsets.right - mScreenEdgeInsets.x,
                    mDisplayInfo.logicalHeight - mTmpInsets.bottom - mScreenEdgeInsets.y);
        }
    }

    /**
     * @return the movement bounds for the given {@param stackBounds} and the current state of the
     *         controller.
     */
    private Rect getMovementBounds(Rect stackBounds) {
        synchronized (mService.mWindowMap) {
            return getMovementBounds(stackBounds, true /* adjustForIme */,
                    true /* adjustForShelf */);
        }
    }

    /**
     * @return the movement bounds for the given {@param stackBounds} and the current state of the
     *         controller.
     */
    private Rect getMovementBounds(Rect stackBounds, boolean adjustForIme, boolean adjustForShelf) {
        synchronized (mService.mWindowMap) {
            final Rect movementBounds = new Rect();
            getInsetBounds(movementBounds);

            // Apply the movement bounds adjustments based on the current state
            mSnapAlgorithm.getMovementBounds(stackBounds, movementBounds, movementBounds,
                    Math.max((adjustForIme && mIsImeShowing) ? mImeHeight : 0,
                            (adjustForShelf && mIsShelfShowing) ? mShelfHeight : 0));
            return movementBounds;
        }
    }

    /**
     * Applies the minimized offsets to the given stack bounds.
     */
    private void applyMinimizedOffset(Rect stackBounds, Rect movementBounds) {
        synchronized (mService.mWindowMap) {
            mTmpDisplaySize.set(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
            mService.getStableInsetsLocked(mDisplayContent.getDisplayId(), mStableInsets);
            mSnapAlgorithm.applyMinimizedOffset(stackBounds, movementBounds, mTmpDisplaySize,
                    mStableInsets);
        }
    }

    /**
     * @return the default snap fraction to apply instead of the default gravity when calculating
     *         the default stack bounds when first entering PiP.
     */
    private float getSnapFraction(Rect stackBounds) {
        return mSnapAlgorithm.getSnapFraction(stackBounds, getMovementBounds(stackBounds));
    }

    /**
     * @return the pixels for a given dp value.
     */
    private int dpToPx(float dpValue, DisplayMetrics dm) {
        return (int) TypedValue.applyDimension(COMPLEX_UNIT_DIP, dpValue, dm);
    }

    void dump(String prefix, PrintWriter pw) {
        pw.println(prefix + "PinnedStackController");
        pw.print(prefix + "  defaultBounds=");
        getDefaultBounds(INVALID_SNAP_FRACTION).printShortString(pw);
        pw.println();
        mService.getStackBounds(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, mTmpRect);
        pw.print(prefix + "  movementBounds="); getMovementBounds(mTmpRect).printShortString(pw);
        pw.println();
        pw.println(prefix + "  mIsImeShowing=" + mIsImeShowing);
        pw.println(prefix + "  mImeHeight=" + mImeHeight);
        pw.println(prefix + "  mIsShelfShowing=" + mIsShelfShowing);
        pw.println(prefix + "  mShelfHeight=" + mShelfHeight);
        pw.println(prefix + "  mReentrySnapFraction=" + mReentrySnapFraction);
        pw.println(prefix + "  mIsMinimized=" + mIsMinimized);
        if (mActions.isEmpty()) {
            pw.println(prefix + "  mActions=[]");
        } else {
            pw.println(prefix + "  mActions=[");
            for (int i = 0; i < mActions.size(); i++) {
                RemoteAction action = mActions.get(i);
                pw.print(prefix + "    Action[" + i + "]: ");
                action.dump("", pw);
            }
            pw.println(prefix + "  ]");
        }
        pw.println(prefix + " mDisplayInfo=" + mDisplayInfo);
    }

    void writeToProto(ProtoOutputStream proto, long fieldId) {
        final long token = proto.start(fieldId);
        getDefaultBounds(INVALID_SNAP_FRACTION).writeToProto(proto, DEFAULT_BOUNDS);
        mService.getStackBounds(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, mTmpRect);
        getMovementBounds(mTmpRect).writeToProto(proto, MOVEMENT_BOUNDS);
        proto.end(token);
    }
}
