/*
 * Copyright (C) 2019 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.systemui.wm;

import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;

import android.annotation.NonNull;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.MergedConfiguration;
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
import android.view.DisplayCutout;
import android.view.DragEvent;
import android.view.IWindow;
import android.view.IWindowManager;
import android.view.IWindowSession;
import android.view.IWindowSessionCallback;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.SurfaceControl;
import android.view.SurfaceControlViewHost;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.WindowlessWindowManager;

import com.android.internal.os.IResultReceiver;

import java.util.HashMap;

import javax.inject.Inject;
import javax.inject.Singleton;

/**
 * Represents the "windowing" layer of the System-UI. This layer allows system-ui components to
 * place and manipulate windows without talking to WindowManager.
 */
@Singleton
public class SystemWindows {
    private static final String TAG = "SystemWindows";

    private final SparseArray<PerDisplay> mPerDisplay = new SparseArray<>();
    final HashMap<View, SurfaceControlViewHost> mViewRoots = new HashMap<>();
    Context mContext;
    IWindowSession mSession;
    DisplayWindowController mDisplayController;
    IWindowManager mWmService;

    private final DisplayWindowController.DisplayWindowListener mDisplayListener =
            new DisplayWindowController.DisplayWindowListener() {
                @Override
                public void onDisplayAdded(int displayId) { }

                @Override
                public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
                    PerDisplay pd = mPerDisplay.get(displayId);
                    if (pd == null) {
                        return;
                    }
                    pd.updateConfiguration(newConfig);
                }

                @Override
                public void onDisplayRemoved(int displayId) { }
            };

    @Inject
    public SystemWindows(Context context, DisplayWindowController displayController,
            IWindowManager wmService) {
        mContext = context;
        mWmService = wmService;
        mDisplayController = displayController;
        mDisplayController.addDisplayWindowListener(mDisplayListener);
        try {
            mSession = wmService.openSession(
                    new IWindowSessionCallback.Stub() {
                        @Override
                        public void onAnimatorScaleChanged(float scale) {}
                    });
        } catch (RemoteException e) {
            Slog.e(TAG, "Unable to create layer", e);
        }
    }

    /**
     * Adds a view to system-ui window management.
     */
    public void addView(View view, WindowManager.LayoutParams attrs, int displayId,
            int windowType) {
        PerDisplay pd = mPerDisplay.get(displayId);
        if (pd == null) {
            pd = new PerDisplay(displayId);
            mPerDisplay.put(displayId, pd);
        }
        pd.addView(view, attrs, windowType);
    }

    /**
     * Removes a view from system-ui window management.
     * @param view
     */
    public void removeView(View view) {
        SurfaceControlViewHost root = mViewRoots.remove(view);
        root.die();
    }

    /**
     * Updates the layout params of a view.
     */
    public void updateViewLayout(@NonNull View view, ViewGroup.LayoutParams params) {
        SurfaceControlViewHost root = mViewRoots.get(view);
        if (root == null || !(params instanceof WindowManager.LayoutParams)) {
            return;
        }
        view.setLayoutParams(params);
        root.relayout((WindowManager.LayoutParams) params);
    }

    /**
     * Adds a root for system-ui window management with no views. Only useful for IME.
     */
    public void addRoot(int displayId, int windowType) {
        PerDisplay pd = mPerDisplay.get(displayId);
        if (pd == null) {
            pd = new PerDisplay(displayId);
            mPerDisplay.put(displayId, pd);
        }
        pd.addRoot(windowType);
    }

    /**
     * Get the IWindow token for a specific root.
     *
     * @param windowType A window type from {@link android.view.WindowManager}.
     */
    IWindow getWindow(int displayId, int windowType) {
        PerDisplay pd = mPerDisplay.get(displayId);
        if (pd == null) {
            return null;
        }
        return pd.getWindow(windowType);
    }

    private class PerDisplay {
        final int mDisplayId;
        private final SparseArray<SysUiWindowManager> mWwms = new SparseArray<>();

        PerDisplay(int displayId) {
            mDisplayId = displayId;
        }

        public void addView(View view, WindowManager.LayoutParams attrs, int windowType) {
            SysUiWindowManager wwm = addRoot(windowType);
            if (wwm == null) {
                Slog.e(TAG, "Unable to create systemui root");
                return;
            }
            final Display display = mDisplayController.getDisplay(mDisplayId);
            SurfaceControlViewHost viewRoot = new SurfaceControlViewHost(mContext, display, wwm);
            attrs.flags |= FLAG_HARDWARE_ACCELERATED;
            viewRoot.addView(view, attrs);
            mViewRoots.put(view, viewRoot);
        }

        SysUiWindowManager addRoot(int windowType) {
            SysUiWindowManager wwm = mWwms.get(windowType);
            if (wwm != null) {
                return wwm;
            }
            SurfaceControl rootSurface = null;
            ContainerWindow win = new ContainerWindow();
            try {
                rootSurface = mWmService.addShellRoot(mDisplayId, win, windowType);
            } catch (RemoteException e) {
            }
            if (rootSurface == null) {
                Slog.e(TAG, "Unable to get root surfacecontrol for systemui");
                return null;
            }
            Context displayContext = mDisplayController.getDisplayContext(mDisplayId);
            wwm = new SysUiWindowManager(mDisplayId, displayContext, rootSurface, win);
            mWwms.put(windowType, wwm);
            return wwm;
        }

        IWindow getWindow(int windowType) {
            SysUiWindowManager wwm = mWwms.get(windowType);
            if (wwm == null) {
                return null;
            }
            return wwm.mContainerWindow;
        }

        void updateConfiguration(Configuration configuration) {
            for (int i = 0; i < mWwms.size(); ++i) {
                mWwms.valueAt(i).updateConfiguration(configuration);
            }
        }
    }

    /**
     * A subclass of WindowlessWindowManager that provides insets to its viewroots.
     */
    public class SysUiWindowManager extends WindowlessWindowManager {
        final int mDisplayId;
        ContainerWindow mContainerWindow;
        public SysUiWindowManager(int displayId, Context ctx, SurfaceControl rootSurface,
                ContainerWindow container) {
            super(ctx.getResources().getConfiguration(), rootSurface, null /* hostInputToken */);
            mContainerWindow = container;
            mDisplayId = displayId;
        }

        @Override
        public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,
                int requestedWidth, int requestedHeight, int viewVisibility, int flags,
                long frameNumber, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
                Rect outVisibleInsets, Rect outStableInsets,
                DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration,
                SurfaceControl outSurfaceControl, InsetsState outInsetsState,
                Point outSurfaceSize, SurfaceControl outBLASTSurfaceControl) {
            int res = super.relayout(window, seq, attrs, requestedWidth, requestedHeight,
                    viewVisibility, flags, frameNumber, outFrame, outOverscanInsets,
                    outContentInsets, outVisibleInsets, outStableInsets,
                    cutout, mergedConfiguration, outSurfaceControl, outInsetsState,
                    outSurfaceSize, outBLASTSurfaceControl);
            if (res != 0) {
                return res;
            }
            DisplayLayout dl = mDisplayController.getDisplayLayout(mDisplayId);
            outStableInsets.set(dl.stableInsets());
            return 0;
        }

        void updateConfiguration(Configuration configuration) {
            setConfiguration(configuration);
        }
    }

    class ContainerWindow extends IWindow.Stub {
        ContainerWindow() {}

        @Override
        public void resized(Rect frame, Rect contentInsets, Rect visibleInsets, Rect stableInsets,
                boolean reportDraw, MergedConfiguration newMergedConfiguration, Rect backDropFrame,
                boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId,
                DisplayCutout.ParcelableWrapper displayCutout) {}

        @Override
        public void locationInParentDisplayChanged(Point offset) {}

        @Override
        public void insetsChanged(InsetsState insetsState) {}

        @Override
        public void insetsControlChanged(InsetsState insetsState,
                InsetsSourceControl[] activeControls) {}

        @Override
        public void showInsets(int types, boolean fromIme) {}

        @Override
        public void hideInsets(int types, boolean fromIme) {}

        @Override
        public void moved(int newX, int newY) {}

        @Override
        public void dispatchAppVisibility(boolean visible) {}

        @Override
        public void dispatchGetNewSurface() {}

        @Override
        public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) {}

        @Override
        public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {}

        @Override
        public void closeSystemDialogs(String reason) {}

        @Override
        public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep,
                boolean sync) {}

        @Override
        public void dispatchWallpaperCommand(String action, int x, int y,
                int z, Bundle extras, boolean sync) {}

        /* Drag/drop */
        @Override
        public void dispatchDragEvent(DragEvent event) {}

        @Override
        public void updatePointerIcon(float x, float y) {}

        @Override
        public void dispatchSystemUiVisibilityChanged(int seq, int globalVisibility,
                int localValue, int localChanges) {}

        @Override
        public void dispatchWindowShown() {}

        @Override
        public void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId) {}

        @Override
        public void dispatchPointerCaptureChanged(boolean hasCapture) {}
    }
}
