/**
 * 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 android.app;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.LauncherApps;
import android.content.pm.ShortcutInfo;
import android.graphics.Insets;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.hardware.display.VirtualDisplay;
import android.os.Bundle;
import android.os.UserHandle;
import android.util.AttributeSet;
import android.util.Log;
import android.view.IWindow;
import android.view.IWindowManager;
import android.view.KeyEvent;
import android.view.SurfaceControl;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.window.TaskEmbedder;
import android.window.TaskOrganizerTaskEmbedder;
import android.window.VirtualDisplayTaskEmbedder;

import dalvik.system.CloseGuard;

/**
 * Task container that allows launching activities into itself.
 * <p>Activity launching into this container is restricted by the same rules that apply to launching
 * on VirtualDisplays.
 * @hide
 */
@TestApi
public class ActivityView extends ViewGroup implements android.window.TaskEmbedder.Host {

    private static final String TAG = "ActivityView";

    private android.window.TaskEmbedder mTaskEmbedder;

    private final SurfaceView mSurfaceView;
    private final SurfaceCallback mSurfaceCallback;

    private final CloseGuard mGuard = CloseGuard.get();
    private boolean mOpened; // Protected by mGuard.

    private final SurfaceControl.Transaction mTmpTransaction = new SurfaceControl.Transaction();

    // For Host
    private final Point mWindowPosition = new Point();
    private final int[] mTmpArray = new int[2];
    private final Rect mTmpRect = new Rect();
    private final Matrix mScreenSurfaceMatrix = new Matrix();
    private final Region mTapExcludeRegion = new Region();

    public ActivityView(Context context) {
        this(context, null /* attrs */);
    }

    public ActivityView(Context context, AttributeSet attrs) {
        this(context, attrs, 0 /* defStyle */);
    }

    public ActivityView(Context context, AttributeSet attrs, int defStyle) {
        this(context, attrs, defStyle, false /*singleTaskInstance*/);
    }

    public ActivityView(Context context, AttributeSet attrs, int defStyle,
            boolean singleTaskInstance) {
        this(context, attrs, defStyle, singleTaskInstance, false /* usePublicVirtualDisplay */);
    }

    /**
     * This constructor let's the caller explicitly request a public virtual display as the backing
     * display. Using a public display is not recommended as it exposes it to other applications,
     * but it might be needed for backwards compatibility.
     */
    public ActivityView(
            @NonNull Context context, @NonNull AttributeSet attrs, int defStyle,
            boolean singleTaskInstance, boolean usePublicVirtualDisplay) {
        super(context, attrs, defStyle);
        if (useTaskOrganizer()) {
            mTaskEmbedder = new TaskOrganizerTaskEmbedder(context, this);
        } else {
            mTaskEmbedder = new VirtualDisplayTaskEmbedder(context, this, singleTaskInstance,
                    usePublicVirtualDisplay);
        }
        mSurfaceView = new SurfaceView(context);
        // Since ActivityView#getAlpha has been overridden, we should use parent class's alpha
        // as master to synchronize surface view's alpha value.
        mSurfaceView.setAlpha(super.getAlpha());
        mSurfaceView.setUseAlpha();
        mSurfaceCallback = new SurfaceCallback();
        mSurfaceView.getHolder().addCallback(mSurfaceCallback);
        addView(mSurfaceView);

        mOpened = true;
        mGuard.open("release");
    }

    /** Callback that notifies when the container is ready or destroyed. */
    public abstract static class StateCallback {

        /**
         * Called when the container is ready for launching activities. Calling
         * {@link #startActivity(Intent)} prior to this callback will result in an
         * {@link IllegalStateException}.
         *
         * @see #startActivity(Intent)
         */
        public abstract void onActivityViewReady(ActivityView view);

        /**
         * Called when the container can no longer launch activities. Calling
         * {@link #startActivity(Intent)} after this callback will result in an
         * {@link IllegalStateException}.
         *
         * @see #startActivity(Intent)
         */
        public abstract void onActivityViewDestroyed(ActivityView view);

        /**
         * Called when a task is created inside the container.
         * This is a filtered version of {@link TaskStackListener}
         */
        public void onTaskCreated(int taskId, ComponentName componentName) { }

        /**
         * Called when a task visibility changes.
         * @hide
         */
        public void onTaskVisibilityChanged(int taskId, boolean visible) { }

        /**
         * Called when a task is moved to the front of the stack inside the container.
         * This is a filtered version of {@link TaskStackListener}
         */
        public void onTaskMovedToFront(int taskId) { }

        /**
         * Called when a task is about to be removed from the stack inside the container.
         * This is a filtered version of {@link TaskStackListener}
         */
        public void onTaskRemovalStarted(int taskId) { }

        /**
         * Called when back is pressed on the root activity of the task.
         * @hide
         */
        public void onBackPressedOnTaskRoot(int taskId) { }
    }

    /**
     * Set the callback to be notified about state changes.
     * <p>This class must finish initializing before {@link #startActivity(Intent)} can be called.
     * <p>Note: If the instance was ready prior to this call being made, then
     * {@link StateCallback#onActivityViewReady(ActivityView)} will be called from within
     * this method call.
     *
     * @param callback The callback to report events to.
     *
     * @see StateCallback
     * @see #startActivity(Intent)
     */
    public void setCallback(StateCallback callback) {
        if (callback == null) {
            mTaskEmbedder.setListener(null);
            return;
        }
        mTaskEmbedder.setListener(new StateCallbackAdapter(callback));
    }

    /**
     * Sets the corner radius for the Activity displayed here. The corners will be
     * cropped from the window painted by the contained Activity.
     *
     * @param cornerRadius the radius for the corners, in pixels
     * @hide
     */
    public void setCornerRadius(float cornerRadius) {
        mSurfaceView.setCornerRadius(cornerRadius);
    }

    /**
     * @hide
     */
    public float getCornerRadius() {
        return mSurfaceView.getCornerRadius();
    }

    /**
     * Control whether the surface is clipped to the same bounds as the View. If true, then
     * the bounds set by {@link #setSurfaceClipBounds(Rect)} are applied to the surface as
     * window-crop.
     *
     * @param clippingEnabled whether to enable surface clipping
     * @hide
     */
    public void setSurfaceClippingEnabled(boolean clippingEnabled) {
        mSurfaceView.setEnableSurfaceClipping(clippingEnabled);
    }

    /**
     * Sets an area on the contained surface to which it will be clipped
     * when it is drawn. Setting the value to null will remove the clip bounds
     * and the surface will draw normally, using its full bounds.
     *
     * @param clipBounds The rectangular area, in the local coordinates of
     * this view, to which future drawing operations will be clipped.
     * @hide
     */
    public void setSurfaceClipBounds(Rect clipBounds) {
        mSurfaceView.setClipBounds(clipBounds);
    }

    /**
     * @hide
     */
    public boolean getSurfaceClipBounds(Rect outRect) {
        return mSurfaceView.getClipBounds(outRect);
    }

    /**
     * Launch an activity represented by {@link ShortcutInfo} into this container.
     * <p>The owner of this container must be allowed to access the shortcut information,
     * as defined in {@link LauncherApps#hasShortcutHostPermission()} to use this method.
     * <p>Activity resolved by the provided {@link ShortcutInfo} must have
     * {@link android.R.attr#resizeableActivity} attribute set to {@code true} in order to be
     * launched here. Also, if activity is not owned by the owner of this container, it must allow
     * embedding and the caller must have permission to embed.
     * <p>Note: This class must finish initializing and
     * {@link StateCallback#onActivityViewReady(ActivityView)} callback must be triggered before
     * this method can be called.
     *
     * @param shortcut the shortcut used to launch the activity.
     * @param options for the activity.
     * @param sourceBounds the rect containing the source bounds of the clicked icon to open
     *                     this shortcut.
     * @see StateCallback
     * @see LauncherApps#startShortcut(ShortcutInfo, Rect, Bundle)
     *
     * @hide
     */
    public void startShortcutActivity(@NonNull ShortcutInfo shortcut,
            @NonNull ActivityOptions options, @Nullable Rect sourceBounds) {
        mTaskEmbedder.startShortcutActivity(shortcut, options, sourceBounds);
    }

    /**
     * Launch a new activity into this container.
     * <p>Activity resolved by the provided {@link Intent} must have
     * {@link android.R.attr#resizeableActivity} attribute set to {@code true} in order to be
     * launched here. Also, if activity is not owned by the owner of this container, it must allow
     * embedding and the caller must have permission to embed.
     * <p>Note: This class must finish initializing and
     * {@link StateCallback#onActivityViewReady(ActivityView)} callback must be triggered before
     * this method can be called.
     *
     * @param intent Intent used to launch an activity.
     *
     * @see StateCallback
     * @see #startActivity(PendingIntent)
     */
    public void startActivity(@NonNull Intent intent) {
        mTaskEmbedder.startActivity(intent);
    }

    /**
     * Launch a new activity into this container.
     * <p>Activity resolved by the provided {@link Intent} must have
     * {@link android.R.attr#resizeableActivity} attribute set to {@code true} in order to be
     * launched here. Also, if activity is not owned by the owner of this container, it must allow
     * embedding and the caller must have permission to embed.
     * <p>Note: This class must finish initializing and
     * {@link StateCallback#onActivityViewReady(ActivityView)} callback must be triggered before
     * this method can be called.
     *
     * @param intent Intent used to launch an activity.
     * @param user The UserHandle of the user to start this activity for.
     *
     *
     * @see StateCallback
     * @see #startActivity(PendingIntent)
     */
    public void startActivity(@NonNull Intent intent, UserHandle user) {
        mTaskEmbedder.startActivity(intent, user);
    }

    /**
     * Launch a new activity into this container.
     * <p>Activity resolved by the provided {@link PendingIntent} must have
     * {@link android.R.attr#resizeableActivity} attribute set to {@code true} in order to be
     * launched here. Also, if activity is not owned by the owner of this container, it must allow
     * embedding and the caller must have permission to embed.
     * <p>Note: This class must finish initializing and
     * {@link StateCallback#onActivityViewReady(ActivityView)} callback must be triggered before
     * this method can be called.
     *
     * @param pendingIntent Intent used to launch an activity.
     *
     * @see StateCallback
     * @see #startActivity(Intent)
     */
    public void startActivity(@NonNull PendingIntent pendingIntent) {
        mTaskEmbedder.startActivity(pendingIntent);
    }

    /**
     * Launch a new activity into this container.
     * <p>Activity resolved by the provided {@link PendingIntent} must have
     * {@link android.R.attr#resizeableActivity} attribute set to {@code true} in order to be
     * launched here. Also, if activity is not owned by the owner of this container, it must allow
     * embedding and the caller must have permission to embed.
     * <p>Note: This class must finish initializing and
     * {@link StateCallback#onActivityViewReady(ActivityView)} callback must be triggered before
     * this method can be called.
     *
     * @param pendingIntent Intent used to launch an activity.
     * @param fillInIntent Additional Intent data, see {@link Intent#fillIn Intent.fillIn()}.
     * @param options options for the activity
     *
     * @see StateCallback
     * @see #startActivity(Intent)
     */
    public void startActivity(@NonNull PendingIntent pendingIntent, @Nullable Intent fillInIntent,
            @NonNull ActivityOptions options) {
        mTaskEmbedder.startActivity(pendingIntent, fillInIntent, options);
    }

    /**
     * Release this container. Activity launching will no longer be permitted.
     * <p>Note: Calling this method is allowed after
     * {@link StateCallback#onActivityViewReady(ActivityView)} callback was triggered and before
     * {@link StateCallback#onActivityViewDestroyed(ActivityView)}.
     *
     * @see StateCallback
     */
    public void release() {
        if (!mTaskEmbedder.isInitialized()) {
            throw new IllegalStateException(
                    "Trying to release container that is not initialized.");
        }
        performRelease();
    }

    /**
     * Triggers an update of {@link ActivityView}'s location in window to properly set tap exclude
     * regions and avoid focus switches by touches on this view.
     */
    public void onLocationChanged() {
        mTaskEmbedder.notifyBoundsChanged();
    }

    @Override
    public void onLayout(boolean changed, int l, int t, int r, int b) {
        mSurfaceView.layout(0 /* left */, 0 /* top */, r - l /* right */, b - t /* bottom */);
    }

    /**
     * Sets the alpha value when the content of {@link SurfaceView} needs to show or hide.
     * <p>Note: The surface view may ignore the alpha value in some cases. Refer to
     * {@link SurfaceView#setAlpha} for more details.
     *
     * @param alpha The opacity of the view.
     */
    @Override
    public void setAlpha(float alpha) {
        super.setAlpha(alpha);

        if (mSurfaceView != null) {
            mSurfaceView.setAlpha(alpha);
        }
    }

    @Override
    public float getAlpha() {
        return mSurfaceView.getAlpha();
    }

    @Override
    public boolean gatherTransparentRegion(Region region) {
        return mTaskEmbedder.gatherTransparentRegion(region)
                || super.gatherTransparentRegion(region);
    }

    private class SurfaceCallback implements SurfaceHolder.Callback {
        @Override
        public void surfaceCreated(SurfaceHolder surfaceHolder) {
            if (!mTaskEmbedder.isInitialized()) {
                initTaskEmbedder(mSurfaceView.getSurfaceControl());
            } else {
                mTmpTransaction.reparent(mTaskEmbedder.getSurfaceControl(),
                        mSurfaceView.getSurfaceControl()).apply();
            }
            mTaskEmbedder.start();
        }

        @Override
        public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {
            mTaskEmbedder.resizeTask(width, height);
            mTaskEmbedder.notifyBoundsChanged();
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
            mTaskEmbedder.stop();
        }
    }

    @Override
    protected void onVisibilityChanged(View changedView, int visibility) {
        super.onVisibilityChanged(changedView, visibility);
        mSurfaceView.setVisibility(visibility);
    }

    /**
     * @return the display id of the virtual display.
     */
    public int getVirtualDisplayId() {
        return mTaskEmbedder.getDisplayId();
    }

    /**
     * @hide
     * @return virtual display.
     */
    public VirtualDisplay getVirtualDisplay() {
        return mTaskEmbedder.getVirtualDisplay();
    }

    /**
     * Injects a pair of down/up key events with keycode {@link KeyEvent#KEYCODE_BACK} to the
     * virtual display.
     */
    public void performBackPress() {
        mTaskEmbedder.performBackPress();
    }

    /**
     * Initializes the task embedder.
     *
     * @param parent control for the surface to parent to
     * @return true if the task embedder has been initialized
     */
    private boolean initTaskEmbedder(SurfaceControl parent) {
        if (!mTaskEmbedder.initialize(parent)) {
            Log.e(TAG, "Failed to initialize ActivityView");
            return false;
        }
        return true;
    }

    private void performRelease() {
        if (!mOpened) {
            return;
        }
        mSurfaceView.getHolder().removeCallback(mSurfaceCallback);
        mTaskEmbedder.release();
        mTaskEmbedder.setListener(null);

        mGuard.close();
        mOpened = false;
    }

    @Override
    protected void finalize() throws Throwable {
        try {
            if (mGuard != null) {
                mGuard.warnIfOpen();
                performRelease();
            }
        } finally {
            super.finalize();
        }
    }

    /**
     * Set forwarded insets on the virtual display.
     *
     * @see IWindowManager#setForwardedInsets
     */
    public void setForwardedInsets(Insets insets) {
        mTaskEmbedder.setForwardedInsets(insets);
    }

    // Host

    /** @hide */
    @Override
    public void onTaskBackgroundColorChanged(android.window.TaskEmbedder ts, int bgColor) {
        if (mSurfaceView != null) {
            mSurfaceView.setResizeBackgroundColor(bgColor);
        }
    }

    /** @hide */
    @Override
    public Region getTapExcludeRegion() {
        if (isAttachedToWindow() && canReceivePointerEvents()) {
            Point windowPos = getPositionInWindow();
            mTapExcludeRegion.set(
                    windowPos.x,
                    windowPos.y,
                    windowPos.x + getWidth(),
                    windowPos.y + getHeight());
            // There might be views on top of us. We need to subtract those areas from the tap
            // exclude region.
            final ViewParent parent = getParent();
            if (parent != null) {
                parent.subtractObscuredTouchableRegion(mTapExcludeRegion, this);
            }
        } else {
            mTapExcludeRegion.setEmpty();
        }
        return mTapExcludeRegion;
    }

    /** @hide */
    @Override
    public Matrix getScreenToTaskMatrix() {
        getLocationOnScreen(mTmpArray);
        mScreenSurfaceMatrix.set(getMatrix());
        mScreenSurfaceMatrix.postTranslate(mTmpArray[0], mTmpArray[1]);
        return mScreenSurfaceMatrix;
    }

    /** @hide */
    @Override
    public Point getPositionInWindow() {
        getLocationInWindow(mTmpArray);
        mWindowPosition.set(mTmpArray[0], mTmpArray[1]);
        return mWindowPosition;
    }

    /** @hide */
    @Override
    public Rect getScreenBounds() {
        getBoundsOnScreen(mTmpRect);
        return mTmpRect;
    }

    /** @hide */
    @Override
    public IWindow getWindow() {
        return super.getWindow();
    }

    /** @hide */
    @Override
    public boolean canReceivePointerEvents() {
        return super.canReceivePointerEvents();
    }

    /**
     * Overridden by instances that require the use of the task organizer implementation instead of
     * the virtual display implementation.  Not for general use.
     * @hide
     */
    protected boolean useTaskOrganizer() {
        return false;
    }

    private final class StateCallbackAdapter implements TaskEmbedder.Listener {
        private final StateCallback mCallback;

        private StateCallbackAdapter(ActivityView.StateCallback cb) {
            mCallback = cb;
        }

        @Override
        public void onInitialized() {
            mCallback.onActivityViewReady(ActivityView.this);
        }

        @Override
        public void onReleased() {
            mCallback.onActivityViewDestroyed(ActivityView.this);
        }

        @Override
        public void onTaskCreated(int taskId, ComponentName name) {
            mCallback.onTaskCreated(taskId, name);
        }

        @Override
        public void onTaskVisibilityChanged(int taskId, boolean visible) {
            mCallback.onTaskVisibilityChanged(taskId, visible);
        }

        @Override
        public void onTaskMovedToFront(int taskId) {
            mCallback.onTaskMovedToFront(taskId);
        }

        @Override
        public void onTaskRemovalStarted(int taskId) {
            mCallback.onTaskRemovalStarted(taskId);
        }

        @Override
        public void onBackPressedOnTaskRoot(int taskId) {
            mCallback.onBackPressedOnTaskRoot(taskId);
        }
    }
}
