/*
 * Copyright (C) 2021 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 androidx.window.extensions.embedding;

import static android.content.pm.PackageManager.MATCH_ALL;

import android.app.Activity;
import android.app.ActivityThread;
import android.app.WindowConfiguration;
import android.app.WindowConfiguration.WindowingMode;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.IBinder;
import android.util.LayoutDirection;
import android.util.Pair;
import android.util.Size;
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowMetrics;
import android.window.WindowContainerTransaction;

import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.internal.annotations.VisibleForTesting;

import java.util.concurrent.Executor;

/**
 * Controls the visual presentation of the splits according to the containers formed by
 * {@link SplitController}.
 */
class SplitPresenter extends JetpackTaskFragmentOrganizer {
    @VisibleForTesting
    static final int POSITION_START = 0;
    @VisibleForTesting
    static final int POSITION_END = 1;
    @VisibleForTesting
    static final int POSITION_FILL = 2;

    @IntDef(value = {
            POSITION_START,
            POSITION_END,
            POSITION_FILL,
    })
    private @interface Position {}

    private final SplitController mController;

    SplitPresenter(@NonNull Executor executor, SplitController controller) {
        super(executor, controller);
        mController = controller;
        registerOrganizer();
    }

    /**
     * Updates the presentation of the provided container.
     */
    void updateContainer(@NonNull TaskFragmentContainer container) {
        final WindowContainerTransaction wct = new WindowContainerTransaction();
        mController.updateContainer(wct, container);
        applyTransaction(wct);
    }

    /**
     * Deletes the specified container and all other associated and dependent containers in the same
     * transaction.
     */
    void cleanupContainer(@NonNull TaskFragmentContainer container, boolean shouldFinishDependent) {
        final WindowContainerTransaction wct = new WindowContainerTransaction();
        cleanupContainer(container, shouldFinishDependent, wct);
        applyTransaction(wct);
    }

    /**
     * Deletes the specified container and all other associated and dependent containers in the same
     * transaction.
     */
    void cleanupContainer(@NonNull TaskFragmentContainer container, boolean shouldFinishDependent,
            @NonNull WindowContainerTransaction wct) {
        container.finish(shouldFinishDependent, this, wct, mController);

        final TaskFragmentContainer newTopContainer = mController.getTopActiveContainer(
                container.getTaskId());
        if (newTopContainer != null) {
            mController.updateContainer(wct, newTopContainer);
        }
    }

    /**
     * Creates a new split with the primary activity and an empty secondary container.
     * @return The newly created secondary container.
     */
    @NonNull
    TaskFragmentContainer createNewSplitWithEmptySideContainer(
            @NonNull WindowContainerTransaction wct, @NonNull Activity primaryActivity,
            @NonNull Intent secondaryIntent, @NonNull SplitPairRule rule) {
        final Rect parentBounds = getParentContainerBounds(primaryActivity);
        final Pair<Size, Size> minDimensionsPair = getActivityIntentMinDimensionsPair(
                primaryActivity, secondaryIntent);
        final Rect primaryRectBounds = getBoundsForPosition(POSITION_START, parentBounds, rule,
                primaryActivity, minDimensionsPair);
        final TaskFragmentContainer primaryContainer = prepareContainerForActivity(wct,
                primaryActivity, primaryRectBounds, null);

        // Create new empty task fragment
        final int taskId = primaryContainer.getTaskId();
        final TaskFragmentContainer secondaryContainer = mController.newContainer(
                secondaryIntent, primaryActivity, taskId);
        final Rect secondaryRectBounds = getBoundsForPosition(POSITION_END, parentBounds,
                rule, primaryActivity, minDimensionsPair);
        final int windowingMode = mController.getTaskContainer(taskId)
                .getWindowingModeForSplitTaskFragment(secondaryRectBounds);
        createTaskFragment(wct, secondaryContainer.getTaskFragmentToken(),
                primaryActivity.getActivityToken(), secondaryRectBounds,
                windowingMode);

        // Set adjacent to each other so that the containers below will be invisible.
        setAdjacentTaskFragments(wct, primaryContainer, secondaryContainer, rule,
                minDimensionsPair);

        mController.registerSplit(wct, primaryContainer, primaryActivity, secondaryContainer, rule);

        return secondaryContainer;
    }

    /**
     * Creates a new split container with the two provided activities.
     * @param primaryActivity An activity that should be in the primary container. If it is not
     *                        currently in an existing container, a new one will be created and the
     *                        activity will be re-parented to it.
     * @param secondaryActivity An activity that should be in the secondary container. If it is not
     *                          currently in an existing container, or if it is currently in the
     *                          same container as the primary activity, a new container will be
     *                          created and the activity will be re-parented to it.
     * @param rule The split rule to be applied to the container.
     */
    void createNewSplitContainer(@NonNull Activity primaryActivity,
            @NonNull Activity secondaryActivity, @NonNull SplitPairRule rule) {
        final WindowContainerTransaction wct = new WindowContainerTransaction();

        final Rect parentBounds = getParentContainerBounds(primaryActivity);
        final Pair<Size, Size> minDimensionsPair = getActivitiesMinDimensionsPair(primaryActivity,
                secondaryActivity);
        final Rect primaryRectBounds = getBoundsForPosition(POSITION_START, parentBounds, rule,
                primaryActivity, minDimensionsPair);
        final TaskFragmentContainer primaryContainer = prepareContainerForActivity(wct,
                primaryActivity, primaryRectBounds, null);

        final Rect secondaryRectBounds = getBoundsForPosition(POSITION_END, parentBounds, rule,
                primaryActivity, minDimensionsPair);
        final TaskFragmentContainer curSecondaryContainer = mController.getContainerWithActivity(
                secondaryActivity);
        TaskFragmentContainer containerToAvoid = primaryContainer;
        if (rule.shouldClearTop() && curSecondaryContainer != null) {
            // Do not reuse the current TaskFragment if the rule is to clear top.
            containerToAvoid = curSecondaryContainer;
        }
        final TaskFragmentContainer secondaryContainer = prepareContainerForActivity(wct,
                secondaryActivity, secondaryRectBounds, containerToAvoid);

        // Set adjacent to each other so that the containers below will be invisible.
        setAdjacentTaskFragments(wct, primaryContainer, secondaryContainer, rule,
                minDimensionsPair);

        mController.registerSplit(wct, primaryContainer, primaryActivity, secondaryContainer, rule);

        applyTransaction(wct);
    }

    /**
     * Creates a new container or resizes an existing container for activity to the provided bounds.
     * @param activity The activity to be re-parented to the container if necessary.
     * @param containerToAvoid Re-parent from this container if an activity is already in it.
     */
    private TaskFragmentContainer prepareContainerForActivity(
            @NonNull WindowContainerTransaction wct, @NonNull Activity activity,
            @NonNull Rect bounds, @Nullable TaskFragmentContainer containerToAvoid) {
        TaskFragmentContainer container = mController.getContainerWithActivity(activity);
        final int taskId = container != null ? container.getTaskId() : activity.getTaskId();
        if (container == null || container == containerToAvoid) {
            container = mController.newContainer(activity, taskId);
            final int windowingMode = mController.getTaskContainer(taskId)
                    .getWindowingModeForSplitTaskFragment(bounds);
            createTaskFragment(wct, container.getTaskFragmentToken(), activity.getActivityToken(),
                    bounds, windowingMode);
            wct.reparentActivityToTaskFragment(container.getTaskFragmentToken(),
                    activity.getActivityToken());
        } else {
            resizeTaskFragmentIfRegistered(wct, container, bounds);
            final int windowingMode = mController.getTaskContainer(taskId)
                    .getWindowingModeForSplitTaskFragment(bounds);
            updateTaskFragmentWindowingModeIfRegistered(wct, container, windowingMode);
        }

        return container;
    }

    /**
     * Starts a new activity to the side, creating a new split container. A new container will be
     * created for the activity that will be started.
     * @param launchingActivity An activity that should be in the primary container. If it is not
     *                          currently in an existing container, a new one will be created and
     *                          the activity will be re-parented to it.
     * @param activityIntent    The intent to start the new activity.
     * @param activityOptions   The options to apply to new activity start.
     * @param rule              The split rule to be applied to the container.
     * @param isPlaceholder     Whether the launch is a placeholder.
     */
    void startActivityToSide(@NonNull Activity launchingActivity, @NonNull Intent activityIntent,
            @Nullable Bundle activityOptions, @NonNull SplitRule rule, boolean isPlaceholder) {
        final Rect parentBounds = getParentContainerBounds(launchingActivity);
        final Pair<Size, Size> minDimensionsPair = getActivityIntentMinDimensionsPair(
                launchingActivity, activityIntent);
        final Rect primaryRectBounds = getBoundsForPosition(POSITION_START, parentBounds, rule,
                launchingActivity, minDimensionsPair);
        final Rect secondaryRectBounds = getBoundsForPosition(POSITION_END, parentBounds, rule,
                launchingActivity, minDimensionsPair);

        TaskFragmentContainer primaryContainer = mController.getContainerWithActivity(
                launchingActivity);
        if (primaryContainer == null) {
            primaryContainer = mController.newContainer(launchingActivity,
                    launchingActivity.getTaskId());
        }

        final int taskId = primaryContainer.getTaskId();
        final TaskFragmentContainer secondaryContainer = mController.newContainer(activityIntent,
                launchingActivity, taskId);
        final int windowingMode = mController.getTaskContainer(taskId)
                .getWindowingModeForSplitTaskFragment(primaryRectBounds);
        final WindowContainerTransaction wct = new WindowContainerTransaction();
        mController.registerSplit(wct, primaryContainer, launchingActivity, secondaryContainer,
                rule);
        startActivityToSide(wct, primaryContainer.getTaskFragmentToken(), primaryRectBounds,
                launchingActivity, secondaryContainer.getTaskFragmentToken(), secondaryRectBounds,
                activityIntent, activityOptions, rule, windowingMode);
        if (isPlaceholder) {
            // When placeholder is launched in split, we should keep the focus on the primary.
            wct.requestFocusOnTaskFragment(primaryContainer.getTaskFragmentToken());
        }
        applyTransaction(wct);
    }

    /**
     * Updates the positions of containers in an existing split.
     * @param splitContainer The split container to be updated.
     * @param updatedContainer The task fragment that was updated and caused this split update.
     * @param wct WindowContainerTransaction that this update should be performed with.
     */
    void updateSplitContainer(@NonNull SplitContainer splitContainer,
            @NonNull TaskFragmentContainer updatedContainer,
            @NonNull WindowContainerTransaction wct) {
        // Getting the parent bounds using the updated container - it will have the recent value.
        final Rect parentBounds = getParentContainerBounds(updatedContainer);
        final SplitRule rule = splitContainer.getSplitRule();
        final TaskFragmentContainer primaryContainer = splitContainer.getPrimaryContainer();
        final Activity activity = primaryContainer.getTopNonFinishingActivity();
        if (activity == null) {
            return;
        }
        final Pair<Size, Size> minDimensionsPair = splitContainer.getMinDimensionsPair();
        final Rect primaryRectBounds = getBoundsForPosition(POSITION_START, parentBounds, rule,
                activity, minDimensionsPair);
        final Rect secondaryRectBounds = getBoundsForPosition(POSITION_END, parentBounds, rule,
                activity, minDimensionsPair);
        final TaskFragmentContainer secondaryContainer = splitContainer.getSecondaryContainer();
        // Whether the placeholder is becoming side-by-side with the primary from fullscreen.
        final boolean isPlaceholderBecomingSplit = splitContainer.isPlaceholderContainer()
                && secondaryContainer.areLastRequestedBoundsEqual(null /* bounds */)
                && !secondaryRectBounds.isEmpty();

        // If the task fragments are not registered yet, the positions will be updated after they
        // are created again.
        resizeTaskFragmentIfRegistered(wct, primaryContainer, primaryRectBounds);
        resizeTaskFragmentIfRegistered(wct, secondaryContainer, secondaryRectBounds);
        setAdjacentTaskFragments(wct, primaryContainer, secondaryContainer, rule,
                minDimensionsPair);
        if (isPlaceholderBecomingSplit) {
            // When placeholder is shown in split, we should keep the focus on the primary.
            wct.requestFocusOnTaskFragment(primaryContainer.getTaskFragmentToken());
        }
        final TaskContainer taskContainer = updatedContainer.getTaskContainer();
        final int windowingMode = taskContainer.getWindowingModeForSplitTaskFragment(
                primaryRectBounds);
        updateTaskFragmentWindowingModeIfRegistered(wct, primaryContainer, windowingMode);
        updateTaskFragmentWindowingModeIfRegistered(wct, secondaryContainer, windowingMode);
    }

    private void setAdjacentTaskFragments(@NonNull WindowContainerTransaction wct,
            @NonNull TaskFragmentContainer primaryContainer,
            @NonNull TaskFragmentContainer secondaryContainer, @NonNull SplitRule splitRule,
            @NonNull Pair<Size, Size> minDimensionsPair) {
        final Rect parentBounds = getParentContainerBounds(primaryContainer);
        // Clear adjacent TaskFragments if the container is shown in fullscreen, or the
        // secondaryContainer could not be finished.
        if (!shouldShowSideBySide(parentBounds, splitRule, minDimensionsPair)) {
            setAdjacentTaskFragments(wct, primaryContainer.getTaskFragmentToken(),
                    null /* secondary */, null /* splitRule */);
        } else {
            setAdjacentTaskFragments(wct, primaryContainer.getTaskFragmentToken(),
                    secondaryContainer.getTaskFragmentToken(), splitRule);
        }
    }

    /**
     * Resizes the task fragment if it was already registered. Skips the operation if the container
     * creation has not been reported from the server yet.
     */
    // TODO(b/190433398): Handle resize if the fragment hasn't appeared yet.
    void resizeTaskFragmentIfRegistered(@NonNull WindowContainerTransaction wct,
            @NonNull TaskFragmentContainer container,
            @Nullable Rect bounds) {
        if (container.getInfo() == null) {
            return;
        }
        resizeTaskFragment(wct, container.getTaskFragmentToken(), bounds);
    }

    private void updateTaskFragmentWindowingModeIfRegistered(
            @NonNull WindowContainerTransaction wct,
            @NonNull TaskFragmentContainer container,
            @WindowingMode int windowingMode) {
        if (container.getInfo() != null) {
            updateWindowingMode(wct, container.getTaskFragmentToken(), windowingMode);
        }
    }

    @Override
    void createTaskFragment(@NonNull WindowContainerTransaction wct, @NonNull IBinder fragmentToken,
            @NonNull IBinder ownerToken, @NonNull Rect bounds, @WindowingMode int windowingMode) {
        final TaskFragmentContainer container = mController.getContainer(fragmentToken);
        if (container == null) {
            throw new IllegalStateException(
                    "Creating a task fragment that is not registered with controller.");
        }

        container.setLastRequestedBounds(bounds);
        container.setLastRequestedWindowingMode(windowingMode);
        super.createTaskFragment(wct, fragmentToken, ownerToken, bounds, windowingMode);
    }

    @Override
    void resizeTaskFragment(@NonNull WindowContainerTransaction wct, @NonNull IBinder fragmentToken,
            @Nullable Rect bounds) {
        TaskFragmentContainer container = mController.getContainer(fragmentToken);
        if (container == null) {
            throw new IllegalStateException(
                    "Resizing a task fragment that is not registered with controller.");
        }

        if (container.areLastRequestedBoundsEqual(bounds)) {
            // Return early if the provided bounds were already requested
            return;
        }

        container.setLastRequestedBounds(bounds);
        super.resizeTaskFragment(wct, fragmentToken, bounds);
    }

    @Override
    void updateWindowingMode(@NonNull WindowContainerTransaction wct,
            @NonNull IBinder fragmentToken, @WindowingMode int windowingMode) {
        final TaskFragmentContainer container = mController.getContainer(fragmentToken);
        if (container == null) {
            throw new IllegalStateException("Setting windowing mode for a task fragment that is"
                    + " not registered with controller.");
        }

        if (container.isLastRequestedWindowingModeEqual(windowingMode)) {
            // Return early if the windowing mode were already requested
            return;
        }

        container.setLastRequestedWindowingMode(windowingMode);
        super.updateWindowingMode(wct, fragmentToken, windowingMode);
    }

    static boolean shouldShowSideBySide(@NonNull Rect parentBounds, @NonNull SplitRule rule) {
        return shouldShowSideBySide(parentBounds, rule, null /* minimumDimensionPair */);
    }

    static boolean shouldShowSideBySide(@NonNull SplitContainer splitContainer) {
        final Rect parentBounds = getParentContainerBounds(splitContainer.getPrimaryContainer());

        return shouldShowSideBySide(parentBounds, splitContainer.getSplitRule(),
                splitContainer.getMinDimensionsPair());
    }

    static boolean shouldShowSideBySide(@NonNull Rect parentBounds, @NonNull SplitRule rule,
            @Nullable Pair<Size, Size> minDimensionsPair) {
        // TODO(b/190433398): Supply correct insets.
        final WindowMetrics parentMetrics = new WindowMetrics(parentBounds,
                new WindowInsets(new Rect()));
        // Don't show side by side if bounds is not qualified.
        if (!rule.checkParentMetrics(parentMetrics)) {
            return false;
        }
        final float splitRatio = rule.getSplitRatio();
        // We only care the size of the bounds regardless of its position.
        final Rect primaryBounds = getPrimaryBounds(parentBounds, splitRatio, true /* isLtr */);
        final Rect secondaryBounds = getSecondaryBounds(parentBounds, splitRatio, true /* isLtr */);

        if (minDimensionsPair == null) {
            return true;
        }
        return !boundsSmallerThanMinDimensions(primaryBounds, minDimensionsPair.first)
                && !boundsSmallerThanMinDimensions(secondaryBounds, minDimensionsPair.second);
    }

    @NonNull
    static Pair<Size, Size> getActivitiesMinDimensionsPair(Activity primaryActivity,
            Activity secondaryActivity) {
        return new Pair<>(getMinDimensions(primaryActivity), getMinDimensions(secondaryActivity));
    }

    @NonNull
    static Pair<Size, Size> getActivityIntentMinDimensionsPair(Activity primaryActivity,
            Intent secondaryIntent) {
        return new Pair<>(getMinDimensions(primaryActivity), getMinDimensions(secondaryIntent));
    }

    @Nullable
    static Size getMinDimensions(@Nullable Activity activity) {
        if (activity == null) {
            return null;
        }
        final ActivityInfo.WindowLayout windowLayout = activity.getActivityInfo().windowLayout;
        if (windowLayout == null) {
            return null;
        }
        return new Size(windowLayout.minWidth, windowLayout.minHeight);
    }

    // TODO(b/232871351): find a light-weight approach for this check.
    @Nullable
    static Size getMinDimensions(@Nullable Intent intent) {
        if (intent == null) {
            return null;
        }
        final PackageManager packageManager = ActivityThread.currentActivityThread()
                .getApplication().getPackageManager();
        final ResolveInfo resolveInfo = packageManager.resolveActivity(intent,
                PackageManager.ResolveInfoFlags.of(MATCH_ALL));
        if (resolveInfo == null) {
            return null;
        }
        final ActivityInfo activityInfo = resolveInfo.activityInfo;
        if (activityInfo == null) {
            return null;
        }
        final ActivityInfo.WindowLayout windowLayout = activityInfo.windowLayout;
        if (windowLayout == null) {
            return null;
        }
        return new Size(windowLayout.minWidth, windowLayout.minHeight);
    }

    static boolean boundsSmallerThanMinDimensions(@NonNull Rect bounds,
            @Nullable Size minDimensions) {
        if (minDimensions == null) {
            return false;
        }
        return bounds.width() < minDimensions.getWidth()
                || bounds.height() < minDimensions.getHeight();
    }

    @VisibleForTesting
    @NonNull
    static Rect getBoundsForPosition(@Position int position, @NonNull Rect parentBounds,
            @NonNull SplitRule rule, @NonNull Activity primaryActivity,
            @Nullable Pair<Size, Size> minDimensionsPair) {
        if (!shouldShowSideBySide(parentBounds, rule, minDimensionsPair)) {
            return new Rect();
        }
        final boolean isLtr = isLtr(primaryActivity, rule);
        final float splitRatio = rule.getSplitRatio();

        switch (position) {
            case POSITION_START:
                return getPrimaryBounds(parentBounds, splitRatio, isLtr);
            case POSITION_END:
                return getSecondaryBounds(parentBounds, splitRatio, isLtr);
            case POSITION_FILL:
            default:
                return new Rect();
        }
    }

    @NonNull
    private static Rect getPrimaryBounds(@NonNull Rect parentBounds, float splitRatio,
            boolean isLtr) {
        return isLtr ? getLeftContainerBounds(parentBounds, splitRatio)
                : getRightContainerBounds(parentBounds, 1 - splitRatio);
    }

    @NonNull
    private static Rect getSecondaryBounds(@NonNull Rect parentBounds, float splitRatio,
            boolean isLtr) {
        return isLtr ? getRightContainerBounds(parentBounds, splitRatio)
                : getLeftContainerBounds(parentBounds, 1 - splitRatio);
    }

    private static Rect getLeftContainerBounds(@NonNull Rect parentBounds, float splitRatio) {
        return new Rect(
                parentBounds.left,
                parentBounds.top,
                (int) (parentBounds.left + parentBounds.width() * splitRatio),
                parentBounds.bottom);
    }

    private static Rect getRightContainerBounds(@NonNull Rect parentBounds, float splitRatio) {
        return new Rect(
                (int) (parentBounds.left + parentBounds.width() * splitRatio),
                parentBounds.top,
                parentBounds.right,
                parentBounds.bottom);
    }

    /**
     * Checks if a split with the provided rule should be displays in left-to-right layout
     * direction, either always or with the current configuration.
     */
    private static boolean isLtr(@NonNull Context context, @NonNull SplitRule rule) {
        switch (rule.getLayoutDirection()) {
            case LayoutDirection.LOCALE:
                return context.getResources().getConfiguration().getLayoutDirection()
                        == View.LAYOUT_DIRECTION_LTR;
            case LayoutDirection.RTL:
                return false;
            case LayoutDirection.LTR:
            default:
                return true;
        }
    }

    @NonNull
    static Rect getParentContainerBounds(@NonNull TaskFragmentContainer container) {
        return container.getTaskContainer().getTaskBounds();
    }

    @NonNull
    Rect getParentContainerBounds(@NonNull Activity activity) {
        final TaskFragmentContainer container = mController.getContainerWithActivity(activity);
        if (container != null) {
            return getParentContainerBounds(container);
        }
        return getTaskBoundsFromActivity(activity);
    }

    @NonNull
    static Rect getTaskBoundsFromActivity(@NonNull Activity activity) {
        final WindowConfiguration windowConfiguration =
                activity.getResources().getConfiguration().windowConfiguration;
        if (!activity.isInMultiWindowMode()) {
            // In fullscreen mode the max bounds should correspond to the task bounds.
            return windowConfiguration.getMaxBounds();
        }
        return windowConfiguration.getBounds();
    }
}
