/*
 * Copyright (C) 2021 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 androidx.window.extensions.embedding;

import static android.os.Process.THREAD_PRIORITY_DISPLAY;
import static android.view.RemoteAnimationTarget.MODE_CLOSING;
import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_CLOSE;
import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE;
import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CHANGE;
import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CLOSE;
import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_OPEN;
import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
import static android.view.WindowManagerPolicyConstants.TYPE_LAYER_OFFSET;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.graphics.Rect;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.RemoteException;
import android.util.Log;
import android.view.IRemoteAnimationFinishedCallback;
import android.view.IRemoteAnimationRunner;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.view.WindowManager;
import android.view.animation.Animation;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;

/** To run the TaskFragment animations. */
class TaskFragmentAnimationRunner extends IRemoteAnimationRunner.Stub {

    private static final String TAG = "TaskFragAnimationRunner";
    private final Handler mHandler;
    private final TaskFragmentAnimationSpec mAnimationSpec;

    TaskFragmentAnimationRunner() {
        HandlerThread animationThread = new HandlerThread(
                "androidx.window.extensions.embedding", THREAD_PRIORITY_DISPLAY);
        animationThread.start();
        mHandler = animationThread.getThreadHandler();
        mAnimationSpec = new TaskFragmentAnimationSpec(mHandler);
    }

    @Nullable
    private Animator mAnimator;

    @Override
    public void onAnimationStart(@WindowManager.TransitionOldType int transit,
            @NonNull RemoteAnimationTarget[] apps,
            @NonNull RemoteAnimationTarget[] wallpapers,
            @NonNull RemoteAnimationTarget[] nonApps,
            @NonNull IRemoteAnimationFinishedCallback finishedCallback) {
        if (wallpapers.length != 0 || nonApps.length != 0) {
            throw new IllegalArgumentException("TaskFragment shouldn't handle animation with"
                    + "wallpaper or non-app windows.");
        }
        if (TaskFragmentAnimationController.DEBUG) {
            Log.v(TAG, "onAnimationStart transit=" + transit);
        }
        mHandler.post(() -> startAnimation(transit, apps, finishedCallback));
    }

    @Override
    public void onAnimationCancelled() {
        if (TaskFragmentAnimationController.DEBUG) {
            Log.v(TAG, "onAnimationCancelled");
        }
        mHandler.post(this::cancelAnimation);
    }

    /** Creates and starts animation. */
    private void startAnimation(@WindowManager.TransitionOldType int transit,
            @NonNull RemoteAnimationTarget[] targets,
            @NonNull IRemoteAnimationFinishedCallback finishedCallback) {
        if (mAnimator != null) {
            Log.w(TAG, "start new animation when the previous one is not finished yet.");
            mAnimator.cancel();
        }
        mAnimator = createAnimator(transit, targets, finishedCallback);
        mAnimator.start();
    }

    /** Cancels animation. */
    private void cancelAnimation() {
        if (mAnimator == null) {
            return;
        }
        mAnimator.cancel();
        mAnimator = null;
    }

    /** Creates the animator given the transition type and windows. */
    private Animator createAnimator(@WindowManager.TransitionOldType int transit,
            @NonNull RemoteAnimationTarget[] targets,
            @NonNull IRemoteAnimationFinishedCallback finishedCallback) {
        final List<TaskFragmentAnimationAdapter> adapters =
                createAnimationAdapters(transit, targets);
        long duration = 0;
        for (TaskFragmentAnimationAdapter adapter : adapters) {
            duration = Math.max(duration, adapter.getDurationHint());
        }
        final ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
        animator.setDuration(duration);
        animator.addUpdateListener((anim) -> {
            // Update all adapters in the same transaction.
            final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
            for (TaskFragmentAnimationAdapter adapter : adapters) {
                adapter.onAnimationUpdate(t, animator.getCurrentPlayTime());
            }
            t.apply();
        });
        animator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {}

            @Override
            public void onAnimationEnd(Animator animation) {
                final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
                for (TaskFragmentAnimationAdapter adapter : adapters) {
                    adapter.onAnimationEnd(t);
                }
                t.apply();

                try {
                    finishedCallback.onAnimationFinished();
                } catch (RemoteException e) {
                    e.rethrowFromSystemServer();
                }
                mAnimator = null;
            }

            @Override
            public void onAnimationCancel(Animator animation) {}

            @Override
            public void onAnimationRepeat(Animator animation) {}
        });
        return animator;
    }

    /** List of {@link TaskFragmentAnimationAdapter} to handle animations on all window targets. */
    private List<TaskFragmentAnimationAdapter> createAnimationAdapters(
            @WindowManager.TransitionOldType int transit,
            @NonNull RemoteAnimationTarget[] targets) {
        switch (transit) {
            case TRANSIT_OLD_ACTIVITY_OPEN:
            case TRANSIT_OLD_TASK_FRAGMENT_OPEN:
            case TRANSIT_OLD_TASK_OPEN:
                return createOpenAnimationAdapters(targets);
            case TRANSIT_OLD_ACTIVITY_CLOSE:
            case TRANSIT_OLD_TASK_FRAGMENT_CLOSE:
            case TRANSIT_OLD_TASK_CLOSE:
                return createCloseAnimationAdapters(targets);
            case TRANSIT_OLD_TASK_FRAGMENT_CHANGE:
                return createChangeAnimationAdapters(targets);
            default:
                throw new IllegalArgumentException("Unhandled transit type=" + transit);
        }
    }

    private List<TaskFragmentAnimationAdapter> createOpenAnimationAdapters(
            @NonNull RemoteAnimationTarget[] targets) {
        return createOpenCloseAnimationAdapters(targets, true /* isOpening */,
                mAnimationSpec::loadOpenAnimation);
    }

    private List<TaskFragmentAnimationAdapter> createCloseAnimationAdapters(
            @NonNull RemoteAnimationTarget[] targets) {
        return createOpenCloseAnimationAdapters(targets, false /* isOpening */,
                mAnimationSpec::loadCloseAnimation);
    }

    /**
     * Creates {@link TaskFragmentAnimationAdapter} for OPEN and CLOSE types of transition.
     * @param isOpening {@code true} for OPEN type, {@code false} for CLOSE type.
     */
    private List<TaskFragmentAnimationAdapter> createOpenCloseAnimationAdapters(
            @NonNull RemoteAnimationTarget[] targets, boolean isOpening,
            @NonNull BiFunction<RemoteAnimationTarget, Rect, Animation> animationProvider) {
        // We need to know if the target window is only a partial of the whole animation screen.
        // If so, we will need to adjust it to make the whole animation screen looks like one.
        final List<RemoteAnimationTarget> openingTargets = new ArrayList<>();
        final List<RemoteAnimationTarget> closingTargets = new ArrayList<>();
        final Rect openingWholeScreenBounds = new Rect();
        final Rect closingWholeScreenBounds = new Rect();
        for (RemoteAnimationTarget target : targets) {
            if (target.mode != MODE_CLOSING) {
                openingTargets.add(target);
                openingWholeScreenBounds.union(target.localBounds);
            } else {
                closingTargets.add(target);
                closingWholeScreenBounds.union(target.localBounds);
            }
        }

        // For OPEN transition, open windows should be above close windows.
        // For CLOSE transition, open windows should be below close windows.
        int offsetLayer = TYPE_LAYER_OFFSET;
        final List<TaskFragmentAnimationAdapter> adapters = new ArrayList<>();
        for (RemoteAnimationTarget target : openingTargets) {
            final TaskFragmentAnimationAdapter adapter = createOpenCloseAnimationAdapter(target,
                    animationProvider, openingWholeScreenBounds);
            if (isOpening) {
                adapter.overrideLayer(offsetLayer++);
            }
            adapters.add(adapter);
        }
        for (RemoteAnimationTarget target : closingTargets) {
            final TaskFragmentAnimationAdapter adapter = createOpenCloseAnimationAdapter(target,
                    animationProvider, closingWholeScreenBounds);
            if (!isOpening) {
                adapter.overrideLayer(offsetLayer++);
            }
            adapters.add(adapter);
        }
        return adapters;
    }

    private TaskFragmentAnimationAdapter createOpenCloseAnimationAdapter(
            @NonNull RemoteAnimationTarget target,
            @NonNull BiFunction<RemoteAnimationTarget, Rect, Animation> animationProvider,
            @NonNull Rect wholeAnimationBounds) {
        final Animation animation = animationProvider.apply(target, wholeAnimationBounds);
        final Rect targetBounds = target.localBounds;
        if (targetBounds.left == wholeAnimationBounds.left
                && targetBounds.right != wholeAnimationBounds.right) {
            // This is the left split of the whole animation window.
            return new TaskFragmentAnimationAdapter.SplitAdapter(animation, target,
                    true /* isLeftHalf */, wholeAnimationBounds.width());
        } else if (targetBounds.left != wholeAnimationBounds.left
                && targetBounds.right == wholeAnimationBounds.right) {
            // This is the right split of the whole animation window.
            return new TaskFragmentAnimationAdapter.SplitAdapter(animation, target,
                    false /* isLeftHalf */, wholeAnimationBounds.width());
        }
        // Open/close window that fills the whole animation.
        return new TaskFragmentAnimationAdapter(animation, target);
    }

    private List<TaskFragmentAnimationAdapter> createChangeAnimationAdapters(
            @NonNull RemoteAnimationTarget[] targets) {
        final List<TaskFragmentAnimationAdapter> adapters = new ArrayList<>();
        for (RemoteAnimationTarget target : targets) {
            if (target.startBounds != null) {
                // This is the target with bounds change.
                final Animation[] animations =
                        mAnimationSpec.createChangeBoundsChangeAnimations(target);
                // Adapter for the starting snapshot leash.
                adapters.add(new TaskFragmentAnimationAdapter.SnapshotAdapter(
                        animations[0], target));
                // Adapter for the ending bounds changed leash.
                adapters.add(new TaskFragmentAnimationAdapter.BoundsChangeAdapter(
                        animations[1], target));
                continue;
            }

            // These are the other targets that don't have bounds change in the same transition.
            final Animation animation;
            if (target.hasAnimatingParent) {
                // No-op if it will be covered by the changing parent window.
                animation = TaskFragmentAnimationSpec.createNoopAnimation(target);
            } else if (target.mode == MODE_CLOSING) {
                animation = mAnimationSpec.createChangeBoundsCloseAnimation(target);
            } else {
                animation = mAnimationSpec.createChangeBoundsOpenAnimation(target);
            }
            adapters.add(new TaskFragmentAnimationAdapter(animation, target));
        }
        return adapters;
    }
}
