/*
 * 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.AppOpsManager.OP_NONE;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.server.wm.WindowContainer.POSITION_TOP;

import android.os.IBinder;
import android.view.IWindow;
import android.view.WindowManager;

import com.android.server.wm.ActivityTestsBase.ActivityBuilder;

/**
 * A collection of static functions that provide access to WindowManager related test functionality.
 */
class WindowTestUtils {

    /** Creates a {@link Task} and adds it to the specified {@link ActivityStack}. */
    static Task createTaskInStack(WindowManagerService service, ActivityStack stack, int userId) {
        synchronized (service.mGlobalLock) {
            final Task task = new ActivityTestsBase.TaskBuilder(
                    stack.mStackSupervisor)
                    .setUserId(userId)
                    .setStack(stack)
                    .build();
            return task;
        }
    }

    /** Creates an {@link ActivityRecord} and adds it to the specified {@link Task}. */
    static ActivityRecord createActivityRecordInTask(DisplayContent dc, Task task) {
        final ActivityRecord activity = createTestActivityRecord(dc);
        task.addChild(activity, POSITION_TOP);
        return activity;
    }

    static ActivityRecord createTestActivityRecord(ActivityStack stack) {
        synchronized (stack.mService.mGlobalLock) {
            final ActivityRecord activity = new ActivityTestsBase.ActivityBuilder(
                    stack.mService)
                    .setStack(stack)
                    .setCreateTask(true)
                    .build();
            postCreateActivitySetup(activity, stack.getDisplayContent());
            return activity;
        }
    }

    static ActivityRecord createTestActivityRecord(DisplayContent dc) {
        synchronized (dc.mWmService.mGlobalLock) {
            final ActivityRecord activity = new ActivityBuilder(dc.mWmService.mAtmService).build();
            postCreateActivitySetup(activity, dc);
            return activity;
        }
    }

    private static void postCreateActivitySetup(ActivityRecord activity, DisplayContent dc) {
        activity.onDisplayChanged(dc);
        activity.setOccludesParent(true);
        activity.setHidden(false);
        activity.hiddenRequested = false;
    }

    static TestWindowToken createTestWindowToken(int type, DisplayContent dc) {
        return createTestWindowToken(type, dc, false /* persistOnEmpty */);
    }

    static TestWindowToken createTestWindowToken(int type, DisplayContent dc,
            boolean persistOnEmpty) {
        synchronized (dc.mWmService.mGlobalLock) {
            return new TestWindowToken(type, dc, persistOnEmpty);
        }
    }

    /* Used so we can gain access to some protected members of the {@link WindowToken} class */
    static class TestWindowToken extends WindowToken {

        private TestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty) {
            super(dc.mWmService, mock(IBinder.class), type, persistOnEmpty, dc,
                    false /* ownerCanManageAppTokens */);
        }

        int getWindowsCount() {
            return mChildren.size();
        }

        boolean hasWindow(WindowState w) {
            return mChildren.contains(w);
        }
    }

    /** Used to track resize reports. */
    static class TestWindowState extends WindowState {
        boolean mResizeReported;

        TestWindowState(WindowManagerService service, Session session, IWindow window,
                WindowManager.LayoutParams attrs, WindowToken token) {
            super(service, session, window, token, null, OP_NONE, 0, attrs, 0, 0,
                    false /* ownerCanAddInternalSystemWindow */);
        }

        @Override
        void reportResized() {
            super.reportResized();
            mResizeReported = true;
        }

        @Override
        public boolean isGoneForLayoutLw() {
            return false;
        }

        @Override
        void updateResizingWindowIfNeeded() {
            // Used in AppWindowTokenTests#testLandscapeSeascapeRotationRelayout to deceive
            // the system that it can actually update the window.
            boolean hadSurface = mHasSurface;
            mHasSurface = true;

            super.updateResizingWindowIfNeeded();

            mHasSurface = hadSurface;
        }
    }
}
