/*
 * Copyright (C) 2020 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.wm.shell.legacysplitscreen;

import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.util.RotationUtils.rotateBounds;
import static android.view.WindowManager.DOCKED_BOTTOM;
import static android.view.WindowManager.DOCKED_INVALID;
import static android.view.WindowManager.DOCKED_LEFT;
import static android.view.WindowManager.DOCKED_RIGHT;
import static android.view.WindowManager.DOCKED_TOP;

import android.annotation.NonNull;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
import android.util.TypedValue;
import android.window.WindowContainerTransaction;

import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.internal.policy.DockedDividerUtils;
import com.android.wm.shell.common.DisplayLayout;

/**
 * Handles split-screen related internal display layout. In general, this represents the
 * WM-facing understanding of the splits.
 */
public class LegacySplitDisplayLayout {
    /** Minimum size of an adjusted stack bounds relative to original stack bounds. Used to
     * restrict IME adjustment so that a min portion of top stack remains visible.*/
    private static final float ADJUSTED_STACK_FRACTION_MIN = 0.3f;

    private static final int DIVIDER_WIDTH_INACTIVE_DP = 4;

    LegacySplitScreenTaskListener mTiles;
    DisplayLayout mDisplayLayout;
    Context mContext;

    // Lazy stuff
    boolean mResourcesValid = false;
    int mDividerSize;
    int mDividerSizeInactive;
    private DividerSnapAlgorithm mSnapAlgorithm = null;
    private DividerSnapAlgorithm mMinimizedSnapAlgorithm = null;
    Rect mPrimary = null;
    Rect mSecondary = null;
    Rect mAdjustedPrimary = null;
    Rect mAdjustedSecondary = null;

    public LegacySplitDisplayLayout(Context ctx, DisplayLayout dl,
            LegacySplitScreenTaskListener taskTiles) {
        mTiles = taskTiles;
        mDisplayLayout = dl;
        mContext = ctx;
    }

    void rotateTo(int newRotation) {
        mDisplayLayout.rotateTo(mContext.getResources(), newRotation);
        final Configuration config = new Configuration();
        config.unset();
        config.orientation = mDisplayLayout.getOrientation();
        Rect tmpRect = new Rect(0, 0, mDisplayLayout.width(), mDisplayLayout.height());
        tmpRect.inset(mDisplayLayout.nonDecorInsets());
        config.windowConfiguration.setAppBounds(tmpRect);
        tmpRect.set(0, 0, mDisplayLayout.width(), mDisplayLayout.height());
        tmpRect.inset(mDisplayLayout.stableInsets());
        config.screenWidthDp = (int) (tmpRect.width() / mDisplayLayout.density());
        config.screenHeightDp = (int) (tmpRect.height() / mDisplayLayout.density());
        mContext = mContext.createConfigurationContext(config);
        mSnapAlgorithm = null;
        mMinimizedSnapAlgorithm = null;
        mResourcesValid = false;
    }

    private void updateResources() {
        if (mResourcesValid) {
            return;
        }
        mResourcesValid = true;
        Resources res = mContext.getResources();
        mDividerSize = DockedDividerUtils.getDividerSize(res,
                DockedDividerUtils.getDividerInsets(res));
        mDividerSizeInactive = (int) TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP, DIVIDER_WIDTH_INACTIVE_DP, res.getDisplayMetrics());
    }

    int getPrimarySplitSide() {
        switch (mDisplayLayout.getNavigationBarPosition(mContext.getResources())) {
            case DisplayLayout.NAV_BAR_BOTTOM:
                return mDisplayLayout.isLandscape() ? DOCKED_LEFT : DOCKED_TOP;
            case DisplayLayout.NAV_BAR_LEFT:
                return DOCKED_RIGHT;
            case DisplayLayout.NAV_BAR_RIGHT:
                return DOCKED_LEFT;
            default:
                return DOCKED_INVALID;
        }
    }

    DividerSnapAlgorithm getSnapAlgorithm() {
        if (mSnapAlgorithm == null) {
            updateResources();
            boolean isHorizontalDivision = !mDisplayLayout.isLandscape();
            mSnapAlgorithm = new DividerSnapAlgorithm(mContext.getResources(),
                    mDisplayLayout.width(), mDisplayLayout.height(), mDividerSize,
                    isHorizontalDivision, mDisplayLayout.stableInsets(), getPrimarySplitSide());
        }
        return mSnapAlgorithm;
    }

    DividerSnapAlgorithm getMinimizedSnapAlgorithm(boolean homeStackResizable) {
        if (mMinimizedSnapAlgorithm == null) {
            updateResources();
            boolean isHorizontalDivision = !mDisplayLayout.isLandscape();
            mMinimizedSnapAlgorithm = new DividerSnapAlgorithm(mContext.getResources(),
                    mDisplayLayout.width(), mDisplayLayout.height(), mDividerSize,
                    isHorizontalDivision, mDisplayLayout.stableInsets(), getPrimarySplitSide(),
                    true /* isMinimized */, homeStackResizable);
        }
        return mMinimizedSnapAlgorithm;
    }

    void resizeSplits(int position) {
        mPrimary = mPrimary == null ? new Rect() : mPrimary;
        mSecondary = mSecondary == null ? new Rect() : mSecondary;
        calcSplitBounds(position, mPrimary, mSecondary);
    }

    void resizeSplits(int position, WindowContainerTransaction t) {
        resizeSplits(position);
        t.setBounds(mTiles.mPrimary.token, mPrimary);
        t.setBounds(mTiles.mSecondary.token, mSecondary);

        t.setSmallestScreenWidthDp(mTiles.mPrimary.token,
                getSmallestWidthDpForBounds(mContext, mDisplayLayout, mPrimary));
        t.setSmallestScreenWidthDp(mTiles.mSecondary.token,
                getSmallestWidthDpForBounds(mContext, mDisplayLayout, mSecondary));
    }

    void calcSplitBounds(int position, @NonNull Rect outPrimary, @NonNull Rect outSecondary) {
        int dockSide = getPrimarySplitSide();
        DockedDividerUtils.calculateBoundsForPosition(position, dockSide, outPrimary,
                mDisplayLayout.width(), mDisplayLayout.height(), mDividerSize);

        DockedDividerUtils.calculateBoundsForPosition(position,
                DockedDividerUtils.invertDockSide(dockSide), outSecondary, mDisplayLayout.width(),
                mDisplayLayout.height(), mDividerSize);
    }

    Rect calcResizableMinimizedHomeStackBounds() {
        DividerSnapAlgorithm.SnapTarget miniMid =
                getMinimizedSnapAlgorithm(true /* resizable */).getMiddleTarget();
        Rect homeBounds = new Rect();
        DockedDividerUtils.calculateBoundsForPosition(miniMid.position,
                DockedDividerUtils.invertDockSide(getPrimarySplitSide()), homeBounds,
                mDisplayLayout.width(), mDisplayLayout.height(), mDividerSize);
        return homeBounds;
    }

    /**
     * Updates the adjustment depending on it's current state.
     */
    void updateAdjustedBounds(int currImeTop, int hiddenTop, int shownTop) {
        adjustForIME(mDisplayLayout, currImeTop, hiddenTop, shownTop, mDividerSize,
                mDividerSizeInactive, mPrimary, mSecondary);
    }

    /** Assumes top/bottom split. Splits are not adjusted for left/right splits. */
    private void adjustForIME(DisplayLayout dl, int currImeTop, int hiddenTop, int shownTop,
            int dividerWidth, int dividerWidthInactive, Rect primaryBounds, Rect secondaryBounds) {
        if (mAdjustedPrimary == null) {
            mAdjustedPrimary = new Rect();
            mAdjustedSecondary = new Rect();
        }

        final Rect displayStableRect = new Rect();
        dl.getStableBounds(displayStableRect);

        final float shownFraction = ((float) (currImeTop - hiddenTop)) / (shownTop - hiddenTop);
        final int currDividerWidth =
                (int) (dividerWidthInactive * shownFraction + dividerWidth * (1.f - shownFraction));

        // Calculate the highest we can move the bottom of the top stack to keep 30% visible.
        final int minTopStackBottom = displayStableRect.top
                + (int) ((mPrimary.bottom - displayStableRect.top) * ADJUSTED_STACK_FRACTION_MIN);
        // Based on that, calculate the maximum amount we'll allow the ime to shift things.
        final int maxOffset = mPrimary.bottom - minTopStackBottom;
        // Calculate how much we would shift things without limits (basically the height of ime).
        final int desiredOffset = hiddenTop - shownTop;
        // Calculate an "adjustedTop" which is the currImeTop but restricted by our constraints.
        // We want an effect where the adjustment only occurs during the "highest" portion of the
        // ime animation. This is done by shifting the adjustment values by the difference in
        // offsets (effectively playing the whole adjustment animation some fixed amount of pixels
        // below the ime top).
        final int topCorrection = Math.max(0, desiredOffset - maxOffset);
        final int adjustedTop = currImeTop + topCorrection;
        // The actual yOffset is the distance between adjustedTop and the bottom of the display.
        // Since our adjustedTop values are playing "below" the ime, we clamp at 0 so we only
        // see adjustment upward.
        final int yOffset = Math.max(0, dl.height() - adjustedTop);

        // TOP
        // Reduce the offset by an additional small amount to squish the divider bar.
        mAdjustedPrimary.set(primaryBounds);
        mAdjustedPrimary.offset(0, -yOffset + (dividerWidth - currDividerWidth));

        // BOTTOM
        mAdjustedSecondary.set(secondaryBounds);
        mAdjustedSecondary.offset(0, -yOffset);
    }

    static int getSmallestWidthDpForBounds(@NonNull Context context, DisplayLayout dl,
            Rect bounds) {
        int dividerSize = DockedDividerUtils.getDividerSize(context.getResources(),
                DockedDividerUtils.getDividerInsets(context.getResources()));

        int minWidth = Integer.MAX_VALUE;

        // Go through all screen orientations and find the orientation in which the task has the
        // smallest width.
        Rect tmpRect = new Rect();
        Rect rotatedDisplayRect = new Rect();
        Rect displayRect = new Rect(0, 0, dl.width(), dl.height());

        DisplayLayout tmpDL = new DisplayLayout();
        for (int rotation = 0; rotation < 4; rotation++) {
            tmpDL.set(dl);
            tmpDL.rotateTo(context.getResources(), rotation);
            DividerSnapAlgorithm snap = initSnapAlgorithmForRotation(context, tmpDL, dividerSize);

            tmpRect.set(bounds);
            rotateBounds(tmpRect, displayRect, dl.rotation(), rotation);
            rotatedDisplayRect.set(0, 0, tmpDL.width(), tmpDL.height());
            final int dockSide = getPrimarySplitSide(tmpRect, rotatedDisplayRect,
                    tmpDL.getOrientation());
            final int position = DockedDividerUtils.calculatePositionForBounds(tmpRect, dockSide,
                    dividerSize);

            final int snappedPosition =
                    snap.calculateNonDismissingSnapTarget(position).position;
            DockedDividerUtils.calculateBoundsForPosition(snappedPosition, dockSide, tmpRect,
                    tmpDL.width(), tmpDL.height(), dividerSize);
            Rect insettedDisplay = new Rect(rotatedDisplayRect);
            insettedDisplay.inset(tmpDL.stableInsets());
            tmpRect.intersect(insettedDisplay);
            minWidth = Math.min(tmpRect.width(), minWidth);
        }
        return (int) (minWidth / dl.density());
    }

    static DividerSnapAlgorithm initSnapAlgorithmForRotation(Context context, DisplayLayout dl,
            int dividerSize) {
        final Configuration config = new Configuration();
        config.unset();
        config.orientation = dl.getOrientation();
        Rect tmpRect = new Rect(0, 0, dl.width(), dl.height());
        tmpRect.inset(dl.nonDecorInsets());
        config.windowConfiguration.setAppBounds(tmpRect);
        tmpRect.set(0, 0, dl.width(), dl.height());
        tmpRect.inset(dl.stableInsets());
        config.screenWidthDp = (int) (tmpRect.width() / dl.density());
        config.screenHeightDp = (int) (tmpRect.height() / dl.density());
        final Context rotationContext = context.createConfigurationContext(config);
        return new DividerSnapAlgorithm(
                rotationContext.getResources(), dl.width(), dl.height(), dividerSize,
                config.orientation == ORIENTATION_PORTRAIT, dl.stableInsets());
    }

    /**
     * Get the current primary-split side. Determined by its location of {@param bounds} within
     * {@param displayRect} but if both are the same, it will try to dock to each side and determine
     * if allowed in its respected {@param orientation}.
     *
     * @param bounds bounds of the primary split task to get which side is docked
     * @param displayRect bounds of the display that contains the primary split task
     * @param orientation the origination of device
     * @return current primary-split side
     */
    static int getPrimarySplitSide(Rect bounds, Rect displayRect, int orientation) {
        if (orientation == ORIENTATION_PORTRAIT) {
            // Portrait mode, docked either at the top or the bottom.
            final int diff = (displayRect.bottom - bounds.bottom) - (bounds.top - displayRect.top);
            if (diff < 0) {
                return DOCKED_BOTTOM;
            } else {
                // Top is default
                return DOCKED_TOP;
            }
        } else if (orientation == ORIENTATION_LANDSCAPE) {
            // Landscape mode, docked either on the left or on the right.
            final int diff = (displayRect.right - bounds.right) - (bounds.left - displayRect.left);
            if (diff < 0) {
                return DOCKED_RIGHT;
            }
            return DOCKED_LEFT;
        }
        return DOCKED_INVALID;
    }
}
