/*
 * Copyright (C) 2017 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.WINDOWING_MODE_UNDEFINED;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;

import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_BOUNDS;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_DONE;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;

import android.annotation.IntDef;
import android.app.ActivityOptions;
import android.content.pm.ActivityInfo.WindowLayout;
import android.graphics.Rect;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;

/**
 * {@link LaunchParamsController} calculates the {@link LaunchParams} by coordinating between
 * registered {@link LaunchParamsModifier}s.
 */
class LaunchParamsController {
    private final ActivityTaskManagerService mService;
    private final LaunchParamsPersister mPersister;
    private final List<LaunchParamsModifier> mModifiers = new ArrayList<>();

    // Temporary {@link LaunchParams} for internal calculations. This is kept separate from
    // {@code mTmpCurrent} and {@code mTmpResult} to prevent clobbering values.
    private final LaunchParams mTmpParams = new LaunchParams();

    private final LaunchParams mTmpCurrent = new LaunchParams();
    private final LaunchParams mTmpResult = new LaunchParams();

    LaunchParamsController(ActivityTaskManagerService service, LaunchParamsPersister persister) {
        mService = service;
        mPersister = persister;
    }

    /**
     * Creates a {@link LaunchParamsController} with default registered
     * {@link LaunchParamsModifier}s.
     */
    void registerDefaultModifiers(ActivityStackSupervisor supervisor) {
        // {@link TaskLaunchParamsModifier} handles window layout preferences.
        registerModifier(new TaskLaunchParamsModifier(supervisor));
    }

    /**
     * Returns the {@link LaunchParams} calculated by the registered modifiers
     * @param task      The {@link TaskRecord} currently being positioned.
     * @param layout    The specified {@link WindowLayout}.
     * @param activity  The {@link ActivityRecord} currently being positioned.
     * @param source    The {@link ActivityRecord} from which activity was started from.
     * @param options   The {@link ActivityOptions} specified for the activity.
     * @param result    The resulting params.
     */
    void calculate(TaskRecord task, WindowLayout layout, ActivityRecord activity,
                   ActivityRecord source, ActivityOptions options, int phase, LaunchParams result) {
        result.reset();

        if (task != null || activity != null) {
            mPersister.getLaunchParams(task, activity, result);
        }

        // We start at the last registered {@link LaunchParamsModifier} as this represents
        // The modifier closest to the product level. Moving back through the list moves closer to
        // the platform logic.
        for (int i = mModifiers.size() - 1; i >= 0; --i) {
            mTmpCurrent.set(result);
            mTmpResult.reset();
            final LaunchParamsModifier modifier = mModifiers.get(i);

            switch(modifier.onCalculate(task, layout, activity, source, options, phase, mTmpCurrent,
                    mTmpResult)) {
                case RESULT_SKIP:
                    // Do not apply any results when we are told to skip
                    continue;
                case RESULT_DONE:
                    // Set result and return immediately.
                    result.set(mTmpResult);
                    return;
                case RESULT_CONTINUE:
                    // Set result and continue
                    result.set(mTmpResult);
                    break;
            }
        }

        if (activity != null && activity.requestedVrComponent != null) {
            // Check if the Activity is a VR activity. If so, it should be launched in main display.
            result.mPreferredDisplayId = DEFAULT_DISPLAY;
        } else if (mService.mVr2dDisplayId != INVALID_DISPLAY) {
            // Get the virtual display ID from ActivityTaskManagerService. If that's set we
            // should always use that.
            result.mPreferredDisplayId = mService.mVr2dDisplayId;
        }
    }

    /**
     * A convenience method for laying out a task.
     * @return {@code true} if bounds were set on the task. {@code false} otherwise.
     */
    boolean layoutTask(TaskRecord task, WindowLayout layout) {
        return layoutTask(task, layout, null /*activity*/, null /*source*/, null /*options*/);
    }

    boolean layoutTask(TaskRecord task, WindowLayout layout, ActivityRecord activity,
            ActivityRecord source, ActivityOptions options) {
        calculate(task, layout, activity, source, options, PHASE_BOUNDS, mTmpParams);

        // No changes, return.
        if (mTmpParams.isEmpty()) {
            return false;
        }

        mService.mWindowManager.deferSurfaceLayout();

        try {
            if (mTmpParams.hasPreferredDisplay()
                    && mTmpParams.mPreferredDisplayId != task.getStack().getDisplay().mDisplayId) {
                mService.moveStackToDisplay(task.getStackId(), mTmpParams.mPreferredDisplayId);
            }

            if (mTmpParams.hasWindowingMode()
                    && mTmpParams.mWindowingMode != task.getStack().getWindowingMode()) {
                task.getStack().setWindowingMode(mTmpParams.mWindowingMode);
            }

            if (mTmpParams.mBounds.isEmpty()) {
                return false;
            }

            if (task.getStack().inFreeformWindowingMode()) {
                // Only set bounds if it's in freeform mode.
                task.updateOverrideConfiguration(mTmpParams.mBounds);
                return true;
            }

            // Setting last non-fullscreen bounds to the bounds so next time the task enters
            // freeform windowing mode it can be in this bounds.
            task.setLastNonFullscreenBounds(mTmpParams.mBounds);
            return false;
        } finally {
            mService.mWindowManager.continueSurfaceLayout();
        }
    }

    /**
     * Adds a modifier to participate in future bounds calculation. Note that the last registered
     * {@link LaunchParamsModifier} will be the first to calculate the bounds.
     */
    void registerModifier(LaunchParamsModifier modifier) {
        if (mModifiers.contains(modifier)) {
            return;
        }

        mModifiers.add(modifier);
    }

    /**
     * A container for holding launch related fields.
     */
    static class LaunchParams {
        /** The bounds within the parent container. */
        final Rect mBounds = new Rect();

        /** The id of the display the {@link TaskRecord} would prefer to be on. */
        int mPreferredDisplayId;

        /** The windowing mode to be in. */
        int mWindowingMode;

        /** Sets values back to default. {@link #isEmpty} will return {@code true} once called. */
        void reset() {
            mBounds.setEmpty();
            mPreferredDisplayId = INVALID_DISPLAY;
            mWindowingMode = WINDOWING_MODE_UNDEFINED;
        }

        /** Copies the values set on the passed in {@link LaunchParams}. */
        void set(LaunchParams params) {
            mBounds.set(params.mBounds);
            mPreferredDisplayId = params.mPreferredDisplayId;
            mWindowingMode = params.mWindowingMode;
        }

        /** Returns {@code true} if no values have been explicitly set. */
        boolean isEmpty() {
            return mBounds.isEmpty() && mPreferredDisplayId == INVALID_DISPLAY
                    && mWindowingMode == WINDOWING_MODE_UNDEFINED;
        }

        boolean hasWindowingMode() {
            return mWindowingMode != WINDOWING_MODE_UNDEFINED;
        }

        boolean hasPreferredDisplay() {
            return mPreferredDisplayId != INVALID_DISPLAY;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            LaunchParams that = (LaunchParams) o;

            if (mPreferredDisplayId != that.mPreferredDisplayId) return false;
            if (mWindowingMode != that.mWindowingMode) return false;
            return mBounds != null ? mBounds.equals(that.mBounds) : that.mBounds == null;
        }

        @Override
        public int hashCode() {
            int result = mBounds != null ? mBounds.hashCode() : 0;
            result = 31 * result + mPreferredDisplayId;
            result = 31 * result + mWindowingMode;
            return result;
        }
    }

    /**
     * An interface implemented by those wanting to participate in bounds calculation.
     */
    interface LaunchParamsModifier {
        @Retention(RetentionPolicy.SOURCE)
        @IntDef({RESULT_SKIP, RESULT_DONE, RESULT_CONTINUE})
        @interface Result {}

        /** Returned when the modifier does not want to influence the bounds calculation */
        int RESULT_SKIP = 0;
        /**
         * Returned when the modifier has changed the bounds and would like its results to be the
         * final bounds applied.
         */
        int RESULT_DONE = 1;
        /**
         * Returned when the modifier has changed the bounds but is okay with other modifiers
         * influencing the bounds.
         */
        int RESULT_CONTINUE = 2;

        @Retention(RetentionPolicy.SOURCE)
        @IntDef({PHASE_DISPLAY, PHASE_WINDOWING_MODE, PHASE_BOUNDS})
        @interface Phase {}

        /**
         * Stops once we are done with preferred display calculation.
         */
        int PHASE_DISPLAY = 0;

        /**
         * Stops once we are done with windowing mode calculation.
         */
        int PHASE_WINDOWING_MODE = 1;

        /**
         * Stops once we are done with window bounds calculation.
         */
        int PHASE_BOUNDS = 2;

        /**
         * Returns the launch params that the provided activity launch params should be overridden
         * to. {@link LaunchParamsModifier} can use this for various purposes, including: 1)
         * Providing default bounds if the launch bounds have not been provided. 2) Repositioning
         * the task so it doesn't get placed over an existing task. 3) Resizing the task so that its
         * dimensions match the activity's requested orientation.
         *
         * @param task          Can be: 1) the target task in which the source activity wants to
         *                      launch the target activity; 2) a newly created task that Android
         *                      gives a chance to override its launching bounds; 3) {@code null} if
         *                      this is called to override an activity's launching bounds.
         * @param layout        Desired layout when activity is first launched.
         * @param activity      Activity that is being started. This can be {@code null} on
         *                      re-parenting an activity to a new task (e.g. for
         *                      Picture-In-Picture). Tasks being created because an activity was
         *                      launched should have this be non-null.
         * @param source        the Activity that launched a new task. Could be {@code null}.
         * @param options       {@link ActivityOptions} used to start the activity with.
         * @param phase         the calculation phase, see {@link LaunchParamsModifier.Phase}
         * @param currentParams launching params after the process of last {@link
         *                      LaunchParamsModifier}.
         * @param outParams     the result params to be set.
         * @return see {@link LaunchParamsModifier.Result}
         */
        @Result
        int onCalculate(TaskRecord task, WindowLayout layout, ActivityRecord activity,
                ActivityRecord source, ActivityOptions options, @Phase int phase,
                LaunchParams currentParams, LaunchParams outParams);
    }
}
