/*
 * Copyright (C) 2015 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 android.util.Slog;
import android.view.Display;

import java.io.PrintWriter;
import java.util.ArrayDeque;

import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.WINDOW_LAYER_MULTIPLIER;

/**
 * Controller for assigning layers to windows on the display.
 *
 * This class encapsulates general algorithm for assigning layers and special rules that we need to
 * apply on top. The general algorithm goes through windows from bottom to the top and the higher
 * the window is, the higher layer is assigned. The final layer is equal to base layer +
 * adjustment from the order. This means that the window list is assumed to be ordered roughly by
 * the base layer (there are exceptions, e.g. due to keyguard and wallpaper and they need to be
 * handled with care, because they break the algorithm).
 *
 * On top of the general algorithm we add special rules, that govern such amazing things as:
 * <li>IME (which has higher base layer, but will be positioned above application windows)</li>
 * <li>docked/pinned windows (that need to be lifted above other application windows, including
 * animations)
 * <li>dock divider (which needs to live above applications, but below IME)</li>
 * <li>replaced windows, which need to live above their normal level, because they anticipate
 * an animation</li>.
 */
public class WindowLayersController {
    private final WindowManagerService mService;

    private int mInputMethodAnimLayerAdjustment;

    public WindowLayersController(WindowManagerService service) {
        mService = service;
    }

    private int mHighestApplicationLayer = 0;
    private ArrayDeque<WindowState> mPinnedWindows = new ArrayDeque<>();
    private ArrayDeque<WindowState> mDockedWindows = new ArrayDeque<>();
    private WindowState mDockDivider = null;
    private ArrayDeque<WindowState> mReplacingWindows = new ArrayDeque<>();

    final void assignLayersLocked(WindowList windows) {
        if (DEBUG_LAYERS) Slog.v(TAG_WM, "Assigning layers based on windows=" + windows,
                new RuntimeException("here").fillInStackTrace());

        clear();
        int curBaseLayer = 0;
        int curLayer = 0;
        boolean anyLayerChanged = false;
        for (int i = 0, windowCount = windows.size(); i < windowCount; i++) {
            final WindowState w = windows.get(i);
            boolean layerChanged = false;

            int oldLayer = w.mLayer;
            if (w.mBaseLayer == curBaseLayer || w.mIsImWindow || (i > 0 && w.mIsWallpaper)) {
                curLayer += WINDOW_LAYER_MULTIPLIER;
            } else {
                curBaseLayer = curLayer = w.mBaseLayer;
            }
            assignAnimLayer(w, curLayer);

            // TODO: Preserved old behavior of code here but not sure comparing
            // oldLayer to mAnimLayer and mLayer makes sense...though the
            // worst case would be unintentionalp layer reassignment.
            if (w.mLayer != oldLayer || w.mWinAnimator.mAnimLayer != oldLayer) {
                layerChanged = true;
                anyLayerChanged = true;
            }

            if (w.mAppToken != null) {
                mHighestApplicationLayer = Math.max(mHighestApplicationLayer,
                        w.mWinAnimator.mAnimLayer);
            }
            collectSpecialWindows(w);

            if (layerChanged) {
                w.scheduleAnimationIfDimming();
            }
        }

        adjustSpecialWindows();

        //TODO (multidisplay): Magnification is supported only for the default display.
        if (mService.mAccessibilityController != null && anyLayerChanged
                && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) {
            mService.mAccessibilityController.onWindowLayersChangedLocked();
        }

        if (DEBUG_LAYERS) logDebugLayers(windows);
    }

    void setInputMethodAnimLayerAdjustment(int adj) {
        if (DEBUG_LAYERS) Slog.v(TAG_WM, "Setting im layer adj to " + adj);
        mInputMethodAnimLayerAdjustment = adj;
        final WindowState imw = mService.mInputMethodWindow;
        if (imw != null) {
            imw.mWinAnimator.mAnimLayer = imw.mLayer + adj;
            if (DEBUG_LAYERS) Slog.v(TAG_WM, "IM win " + imw
                    + " anim layer: " + imw.mWinAnimator.mAnimLayer);
            for (int i = imw.mChildWindows.size() - 1; i >= 0; i--) {
                final WindowState childWindow = imw.mChildWindows.get(i);
                childWindow.mWinAnimator.mAnimLayer = childWindow.mLayer + adj;
                if (DEBUG_LAYERS) Slog.v(TAG_WM, "IM win " + childWindow
                        + " anim layer: " + childWindow.mWinAnimator.mAnimLayer);
            }
        }
        for (int i = mService.mInputMethodDialogs.size() - 1; i >= 0; i--) {
            final WindowState dialog = mService.mInputMethodDialogs.get(i);
            dialog.mWinAnimator.mAnimLayer = dialog.mLayer + adj;
            if (DEBUG_LAYERS) Slog.v(TAG_WM, "IM win " + imw
                    + " anim layer: " + dialog.mWinAnimator.mAnimLayer);
        }
    }

    int getSpecialWindowAnimLayerAdjustment(WindowState win) {
        if (win.mIsImWindow) {
            return mInputMethodAnimLayerAdjustment;
        } else if (win.mIsWallpaper) {
            return mService.mWallpaperControllerLocked.getAnimLayerAdjustment();
        }
        return 0;
    }

    /**
     * @return The layer used for dimming the apps when dismissing docked/fullscreen stack. Just
     *         above all application surfaces.
     */
    int getResizeDimLayer() {
        return mDockDivider.mLayer - 1;
    }

    private void logDebugLayers(WindowList windows) {
        for (int i = 0, n = windows.size(); i < n; i++) {
            final WindowState w = windows.get(i);
            final WindowStateAnimator winAnimator = w.mWinAnimator;
            Slog.v(TAG_WM, "Assign layer " + w + ": " + "mBase=" + w.mBaseLayer
                    + " mLayer=" + w.mLayer + (w.mAppToken == null
                    ? "" : " mAppLayer=" + w.mAppToken.mAppAnimator.animLayerAdjustment)
                    + " =mAnimLayer=" + winAnimator.mAnimLayer);
        }
    }

    private void clear() {
        mHighestApplicationLayer = 0;
        mPinnedWindows.clear();
        mDockedWindows.clear();
        mReplacingWindows.clear();
        mDockDivider = null;
    }

    private void collectSpecialWindows(WindowState w) {
        if (w.mAttrs.type == TYPE_DOCK_DIVIDER) {
            mDockDivider = w;
            return;
        }
        if (w.mWillReplaceWindow) {
            mReplacingWindows.add(w);
        }
        final TaskStack stack = w.getStack();
        if (stack == null) {
            return;
        }
        if (stack.mStackId == PINNED_STACK_ID) {
            mPinnedWindows.add(w);
        } else if (stack.mStackId == DOCKED_STACK_ID) {
            mDockedWindows.add(w);
        }
    }

    private void adjustSpecialWindows() {
        int layer = mHighestApplicationLayer + 1;
        // For pinned and docked stack window, we want to make them above other windows also when
        // these windows are animating.
        while (!mDockedWindows.isEmpty()) {
            layer = assignAndIncreaseLayerIfNeeded(mDockedWindows.remove(), layer);
        }

        // Leave some space here so the dim layer while dismissing docked/fullscreen stack has space
        // below the divider but above the app windows. It needs to be below the divider in because
        // the divider sometimes overlaps the app windows.
        layer++;
        layer = assignAndIncreaseLayerIfNeeded(mDockDivider, layer);
        // We know that we will be animating a relaunching window in the near future, which will
        // receive a z-order increase. We want the replaced window to immediately receive the same
        // treatment, e.g. to be above the dock divider.
        while (!mReplacingWindows.isEmpty()) {
            layer = assignAndIncreaseLayerIfNeeded(mReplacingWindows.remove(), layer);
        }

        while (!mPinnedWindows.isEmpty()) {
            layer = assignAndIncreaseLayerIfNeeded(mPinnedWindows.remove(), layer);
        }
    }

    private int assignAndIncreaseLayerIfNeeded(WindowState win, int layer) {
        if (win != null) {
            assignAnimLayer(win, layer);
            layer++;
        }
        return layer;
    }
    
    private void assignAnimLayer(WindowState w, int layer) {
        w.mLayer = layer;
        w.mWinAnimator.mAnimLayer = w.mLayer + w.getAnimLayerAdjustment() +
                    getSpecialWindowAnimLayerAdjustment(w);
        if (w.mAppToken != null && w.mAppToken.mAppAnimator.thumbnailForceAboveLayer > 0
                && w.mWinAnimator.mAnimLayer > w.mAppToken.mAppAnimator.thumbnailForceAboveLayer) {
            w.mAppToken.mAppAnimator.thumbnailForceAboveLayer = w.mWinAnimator.mAnimLayer;
        }
    }

    void dump(PrintWriter pw, String s) {
        if (mInputMethodAnimLayerAdjustment != 0 ||
                mService.mWallpaperControllerLocked.getAnimLayerAdjustment() != 0) {
            pw.print("  mInputMethodAnimLayerAdjustment=");
            pw.print(mInputMethodAnimLayerAdjustment);
            pw.print("  mWallpaperAnimLayerAdjustment=");
            pw.println(mService.mWallpaperControllerLocked.getAnimLayerAdjustment());
        }
    }
}
