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

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.util.ArrayMap;
import android.util.Slog;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;

import com.android.internal.annotations.VisibleForTesting;

import java.io.PrintWriter;

/**
 * A class that can run animations on objects that have a set of child surfaces. We do this by
 * reparenting all child surfaces of an object onto a new surface, called the "Leash". The Leash
 * gets attached in the surface hierarchy where the the children were attached to. We then hand off
 * the Leash to the component handling the animation, which is specified by the
 * {@link AnimationAdapter}. When the animation is done animating, our callback to finish the
 * animation will be invoked, at which we reparent the children back to the original parent.
 */
class SurfaceAnimator {

    private static final String TAG = TAG_WITH_CLASS_NAME ? "SurfaceAnimator" : TAG_WM;
    private final WindowManagerService mService;
    private AnimationAdapter mAnimation;

    @VisibleForTesting
    SurfaceControl mLeash;
    private final Animatable mAnimatable;
    private final OnAnimationFinishedCallback mInnerAnimationFinishedCallback;
    private final Runnable mAnimationFinishedCallback;
    private boolean mAnimationStartDelayed;

    /**
     * @param animatable The object to animate.
     * @param animationFinishedCallback Callback to invoke when an animation has finished running.
     */
    SurfaceAnimator(Animatable animatable, Runnable animationFinishedCallback,
            WindowManagerService service) {
        mAnimatable = animatable;
        mService = service;
        mAnimationFinishedCallback = animationFinishedCallback;
        mInnerAnimationFinishedCallback = getFinishedCallback(animationFinishedCallback);
    }

    private OnAnimationFinishedCallback getFinishedCallback(Runnable animationFinishedCallback) {
        return anim -> {
            synchronized (mService.mWindowMap) {
                final SurfaceAnimator target = mService.mAnimationTransferMap.remove(anim);
                if (target != null) {
                    target.mInnerAnimationFinishedCallback.onAnimationFinished(anim);
                    return;
                }

                // TODO: This should use pendingTransaction eventually, but right now things
                // happening on the animation finished callback are happening on the global
                // transaction.
                // For now we need to run this after it's guaranteed that the transaction that
                // reparents the surface onto the leash is executed already. Otherwise this may be
                // executed first, leading to surface loss, as the reparent operations wouldn't
                // be in order.
                mService.mAnimator.addAfterPrepareSurfacesRunnable(() -> {
                    if (anim != mAnimation) {
                        // Callback was from another animation - ignore.
                        return;
                    }
                    final Transaction t = new Transaction();
                    SurfaceControl.openTransaction();
                    try {
                        reset(t, true /* destroyLeash */);
                        animationFinishedCallback.run();
                    } finally {
                        SurfaceControl.mergeToGlobalTransaction(t);
                        SurfaceControl.closeTransaction();
                    }
                });
            }
        };
    }

    /**
     * Starts an animation.
     *
     * @param anim The object that bridges the controller, {@link SurfaceAnimator}, with the
     *             component responsible for running the animation. It runs the animation with
     *             {@link AnimationAdapter#startAnimation} once the hierarchy with
     *             the Leash has been set up.
     * @param hidden Whether the container holding the child surfaces is currently visible or not.
     *               This is important as it will start with the leash hidden or visible before
     *               handing it to the component that is responsible to run the animation.
     */
    void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden) {
        cancelAnimation(t, true /* restarting */, true /* forwardCancel */);
        mAnimation = anim;
        final SurfaceControl surface = mAnimatable.getSurfaceControl();
        if (surface == null) {
            Slog.w(TAG, "Unable to start animation, surface is null or no children.");
            cancelAnimation();
            return;
        }
        mLeash = createAnimationLeash(surface, t,
                mAnimatable.getSurfaceWidth(), mAnimatable.getSurfaceHeight(), hidden);
        mAnimatable.onAnimationLeashCreated(t, mLeash);
        if (mAnimationStartDelayed) {
            if (DEBUG_ANIM) Slog.i(TAG, "Animation start delayed");
            return;
        }
        mAnimation.startAnimation(mLeash, t, mInnerAnimationFinishedCallback);
    }

    /**
     * Begins with delaying all animations to start. Any subsequent call to {@link #startAnimation}
     * will not start the animation until {@link #endDelayingAnimationStart} is called. When an
     * animation start is being delayed, the animator is considered animating already.
     */
    void startDelayingAnimationStart() {

        // We only allow delaying animation start we are not currently animating
        if (!isAnimating()) {
            mAnimationStartDelayed = true;
        }
    }

    /**
     * See {@link #startDelayingAnimationStart}.
     */
    void endDelayingAnimationStart() {
        final boolean delayed = mAnimationStartDelayed;
        mAnimationStartDelayed = false;
        if (delayed && mAnimation != null) {
            mAnimation.startAnimation(mLeash, mAnimatable.getPendingTransaction(),
                    mInnerAnimationFinishedCallback);
            mAnimatable.commitPendingTransaction();
        }
    }

    /**
     * @return Whether we are currently running an animation, or we have a pending animation that
     *         is waiting to be started with {@link #endDelayingAnimationStart}
     */
    boolean isAnimating() {
        return mAnimation != null;
    }

    /**
     * @return The current animation spec if we are running an animation, or {@code null} otherwise.
     */
    AnimationAdapter getAnimation() {
        return mAnimation;
    }

    /**
     * Cancels any currently running animation.
     */
    void cancelAnimation() {
        cancelAnimation(mAnimatable.getPendingTransaction(), false /* restarting */,
                true /* forwardCancel */);
        mAnimatable.commitPendingTransaction();
    }

    /**
     * Sets the layer of the surface.
     * <p>
     * When the layer of the surface needs to be adjusted, we need to set it on the leash if the
     * surface is reparented to the leash. This method takes care of that.
     */
    void setLayer(Transaction t, int layer) {
        t.setLayer(mLeash != null ? mLeash : mAnimatable.getSurfaceControl(), layer);
    }

    /**
     * Sets the surface to be relatively layered.
     *
     * @see #setLayer
     */
    void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
        t.setRelativeLayer(mLeash != null ? mLeash : mAnimatable.getSurfaceControl(), relativeTo, layer);
    }

    /**
     * Reparents the surface.
     *
     * @see #setLayer
     */
    void reparent(Transaction t, SurfaceControl newParent) {
        t.reparent(mLeash != null ? mLeash : mAnimatable.getSurfaceControl(), newParent.getHandle());
    }

    /**
     * @return True if the surface is attached to the leash; false otherwise.
     */
    boolean hasLeash() {
        return mLeash != null;
    }

    void transferAnimation(SurfaceAnimator from) {
        if (from.mLeash == null) {
            return;
        }
        final SurfaceControl surface = mAnimatable.getSurfaceControl();
        final SurfaceControl parent = mAnimatable.getAnimationLeashParent();
        if (surface == null || parent == null) {
            Slog.w(TAG, "Unable to transfer animation, surface or parent is null");
            cancelAnimation();
            return;
        }
        endDelayingAnimationStart();
        final Transaction t = mAnimatable.getPendingTransaction();
        cancelAnimation(t, true /* restarting */, true /* forwardCancel */);
        mLeash = from.mLeash;
        mAnimation = from.mAnimation;

        // Cancel source animation, but don't let animation runner cancel the animation.
        from.cancelAnimation(t, false /* restarting */, false /* forwardCancel */);
        t.reparent(surface, mLeash.getHandle());
        t.reparent(mLeash, parent.getHandle());
        mAnimatable.onAnimationLeashCreated(t, mLeash);
        mService.mAnimationTransferMap.put(mAnimation, this);
    }

    /**
     * Cancels the animation, and resets the leash.
     *
     * @param t The transaction to use for all cancelling surface operations.
     * @param restarting Whether we are restarting the animation.
     * @param forwardCancel Whether to forward the cancel signal to the adapter executing the
     *                      animation. This will be set to false when just transferring an animation
     *                      to another animator.
     */
    private void cancelAnimation(Transaction t, boolean restarting, boolean forwardCancel) {
        if (DEBUG_ANIM) Slog.i(TAG, "Cancelling animation restarting=" + restarting);
        final SurfaceControl leash = mLeash;
        final AnimationAdapter animation = mAnimation;
        reset(t, forwardCancel);
        if (animation != null) {
            if (!mAnimationStartDelayed && forwardCancel) {
                animation.onAnimationCancelled(leash);
            }
            if (!restarting) {
                mAnimationFinishedCallback.run();
            }
        }
        if (!restarting) {
            mAnimationStartDelayed = false;
        }
    }

    private void reset(Transaction t, boolean destroyLeash) {
        final SurfaceControl surface = mAnimatable.getSurfaceControl();
        final SurfaceControl parent = mAnimatable.getParentSurfaceControl();

        // If the surface was destroyed, we don't care to reparent it back.
        final boolean destroy = mLeash != null && surface != null && parent != null;
        if (destroy) {
            if (DEBUG_ANIM) Slog.i(TAG, "Reparenting to original parent");
            t.reparent(surface, parent.getHandle());
        }
        mService.mAnimationTransferMap.remove(mAnimation);
        if (mLeash != null && destroyLeash) {
            mAnimatable.destroyAfterPendingTransaction(mLeash);
        }
        mLeash = null;
        mAnimation = null;

        // Make sure to inform the animatable after the leash was destroyed.
        if (destroy) {
            mAnimatable.onAnimationLeashDestroyed(t);
        }
    }

    private SurfaceControl createAnimationLeash(SurfaceControl surface, Transaction t, int width,
            int height, boolean hidden) {
        if (DEBUG_ANIM) Slog.i(TAG, "Reparenting to leash");
        final SurfaceControl.Builder builder = mAnimatable.makeAnimationLeash()
                .setParent(mAnimatable.getAnimationLeashParent())
                .setName(surface + " - animation-leash")
                .setSize(width, height);
        final SurfaceControl leash = builder.build();
        if (!hidden) {
            t.show(leash);
        }
        t.reparent(surface, leash.getHandle());
        return leash;
    }

    void dump(PrintWriter pw, String prefix) {
        pw.print(prefix); pw.print("mAnimation="); pw.print(mAnimation);
        pw.print(" mLeash="); pw.println(mLeash);
    }

    /**
     * Callback to be passed into {@link AnimationAdapter#startAnimation} to be invoked by the
     * component that is running the animation when the animation is finished.
     */
    interface OnAnimationFinishedCallback {
        void onAnimationFinished(AnimationAdapter anim);
    }

    /**
     * Interface to be animated by {@link SurfaceAnimator}.
     */
    interface Animatable {

        /**
         * @return The pending transaction that will be committed in the next frame.
         */
        @NonNull Transaction getPendingTransaction();

        /**
         * Schedules a commit of the pending transaction.
         */
        void commitPendingTransaction();

        /**
         * Called when the was created.
         *
         * @param t The transaction to use to apply any necessary changes.
         * @param leash The leash that was created.
         */
        void onAnimationLeashCreated(Transaction t, SurfaceControl leash);

        /**
         * Called when the leash is being destroyed, and the surface was reparented back to the
         * original parent.
         *
         * @param t The transaction to use to apply any necessary changes.
         */
        void onAnimationLeashDestroyed(Transaction t);

        /**
         * Destroy a given surface after executing {@link #getPendingTransaction}.
         *
         * @see WindowContainer#destroyAfterPendingTransaction
         */
        void destroyAfterPendingTransaction(SurfaceControl surface);

        /**
         * @return A new surface to be used for the animation leash, inserted at the correct
         *         position in the hierarchy.
         */
        SurfaceControl.Builder makeAnimationLeash();

        /**
         * @return The parent that should be used for the animation leash.
         */
        @Nullable SurfaceControl getAnimationLeashParent();

        /**
         * @return The surface of the object to be animated.
         */
        @Nullable SurfaceControl getSurfaceControl();

        /**
         * @return The parent of the surface object to be animated.
         */
        @Nullable SurfaceControl getParentSurfaceControl();

        /**
         * @return The width of the surface to be animated.
         */
        int getSurfaceWidth();

        /**
         * @return The height of the surface to be animated.
         */
        int getSurfaceHeight();
    }
}
