/*
 * 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 com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;

import android.annotation.Nullable;
import android.app.IActivityManager;
import android.os.RemoteException;
import android.os.Handler;
import android.os.Looper;
import android.util.Slog;
import android.view.Display;
import android.view.IWindow;
import com.android.internal.annotations.GuardedBy;
import com.android.server.input.InputManagerService;
import com.android.server.input.InputWindowHandle;

/**
 * Controller for task positioning by drag.
 */
class TaskPositioningController {
    private final WindowManagerService mService;
    private final InputManagerService mInputManager;
    private final InputMonitor mInputMonitor;
    private final IActivityManager mActivityManager;
    private final Handler mHandler;

    @GuardedBy("WindowManagerSerivce.mWindowMap")
    private @Nullable TaskPositioner mTaskPositioner;

    boolean isPositioningLocked() {
        return mTaskPositioner != null;
    }

    InputWindowHandle getDragWindowHandleLocked() {
        return mTaskPositioner != null ? mTaskPositioner.mDragWindowHandle : null;
    }

    TaskPositioningController(WindowManagerService service, InputManagerService inputManager,
            InputMonitor inputMonitor, IActivityManager activityManager, Looper looper) {
        mService = service;
        mInputMonitor = inputMonitor;
        mInputManager = inputManager;
        mActivityManager = activityManager;
        mHandler = new Handler(looper);
    }

    boolean startMovingTask(IWindow window, float startX, float startY) {
        WindowState win = null;
        synchronized (mService.mWindowMap) {
            win = mService.windowForClientLocked(null, window, false);
            // win shouldn't be null here, pass it down to startPositioningLocked
            // to get warning if it's null.
            if (!startPositioningLocked(
                    win, false /*resize*/, false /*preserveOrientation*/, startX, startY)) {
                return false;
            }
        }
        try {
            mActivityManager.setFocusedTask(win.getTask().mTaskId);
        } catch(RemoteException e) {}
        return true;
    }

    void handleTapOutsideTask(DisplayContent displayContent, int x, int y) {
        mHandler.post(() -> {
            int taskId = -1;
            synchronized (mService.mWindowMap) {
                final Task task = displayContent.findTaskForResizePoint(x, y);
                if (task != null) {
                    if (!startPositioningLocked(task.getTopVisibleAppMainWindow(), true /*resize*/,
                            task.preserveOrientationOnResize(), x, y)) {
                        return;
                    }
                    taskId = task.mTaskId;
                } else {
                    taskId = displayContent.taskIdFromPoint(x, y);
                }
            }
            if (taskId >= 0) {
                try {
                    mActivityManager.setFocusedTask(taskId);
                } catch (RemoteException e) {
                }
            }
        });
    }

    private boolean startPositioningLocked(WindowState win, boolean resize,
            boolean preserveOrientation, float startX, float startY) {
        if (DEBUG_TASK_POSITIONING)
            Slog.d(TAG_WM, "startPositioningLocked: "
                    + "win=" + win + ", resize=" + resize + ", preserveOrientation="
                    + preserveOrientation + ", {" + startX + ", " + startY + "}");

        if (win == null || win.getAppToken() == null) {
            Slog.w(TAG_WM, "startPositioningLocked: Bad window " + win);
            return false;
        }
        if (win.mInputChannel == null) {
            Slog.wtf(TAG_WM, "startPositioningLocked: " + win + " has no input channel, "
                    + " probably being removed");
            return false;
        }

        final DisplayContent displayContent = win.getDisplayContent();
        if (displayContent == null) {
            Slog.w(TAG_WM, "startPositioningLocked: Invalid display content " + win);
            return false;
        }

        Display display = displayContent.getDisplay();
        mTaskPositioner = new TaskPositioner(mService);
        mTaskPositioner.register(displayContent);
        mInputMonitor.updateInputWindowsLw(true /*force*/);

        // We need to grab the touch focus so that the touch events during the
        // resizing/scrolling are not sent to the app. 'win' is the main window
        // of the app, it may not have focus since there might be other windows
        // on top (eg. a dialog window).
        WindowState transferFocusFromWin = win;
        if (mService.mCurrentFocus != null && mService.mCurrentFocus != win
                && mService.mCurrentFocus.mAppToken == win.mAppToken) {
            transferFocusFromWin = mService.mCurrentFocus;
        }
        if (!mInputManager.transferTouchFocus(
                transferFocusFromWin.mInputChannel, mTaskPositioner.mServerChannel)) {
            Slog.e(TAG_WM, "startPositioningLocked: Unable to transfer touch focus");
            mTaskPositioner.unregister();
            mTaskPositioner = null;
            mInputMonitor.updateInputWindowsLw(true /*force*/);
            return false;
        }

        mTaskPositioner.startDrag(win, resize, preserveOrientation, startX, startY);
        return true;
    }

    void finishTaskPositioning() {
        mHandler.post(() -> {
            if (DEBUG_TASK_POSITIONING) Slog.d(TAG_WM, "finishPositioning");

            synchronized (mService.mWindowMap) {
                if (mTaskPositioner != null) {
                    mTaskPositioner.unregister();
                    mTaskPositioner = null;
                    mInputMonitor.updateInputWindowsLw(true /*force*/);
                }
            }
        });
    }
}
