/*
 * Copyright (C) 2016 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.pip.phone;

import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;

import android.app.ActivityManager.StackInfo;
import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
import android.app.RemoteAction;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ParceledListSlice;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Debug;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.util.Log;
import android.view.MotionEvent;

import com.android.systemui.pip.phone.PipMediaController.ActionListener;
import com.android.systemui.shared.system.InputConsumerController;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

/**
 * Manages the PiP menu activity which can show menu options or a scrim.
 *
 * The current media session provides actions whenever there are no valid actions provided by the
 * current PiP activity. Otherwise, those actions always take precedence.
 */
public class PipMenuActivityController {

    private static final String TAG = "PipMenuActController";
    private static final boolean DEBUG = false;

    public static final String EXTRA_CONTROLLER_MESSENGER = "messenger";
    public static final String EXTRA_ACTIONS = "actions";
    public static final String EXTRA_STACK_BOUNDS = "stack_bounds";
    public static final String EXTRA_MOVEMENT_BOUNDS = "movement_bounds";
    public static final String EXTRA_ALLOW_TIMEOUT = "allow_timeout";
    public static final String EXTRA_WILL_RESIZE_MENU = "resize_menu_on_show";
    public static final String EXTRA_DISMISS_FRACTION = "dismiss_fraction";
    public static final String EXTRA_MENU_STATE = "menu_state";

    public static final int MESSAGE_MENU_STATE_CHANGED = 100;
    public static final int MESSAGE_EXPAND_PIP = 101;
    public static final int MESSAGE_DISMISS_PIP = 103;
    public static final int MESSAGE_UPDATE_ACTIVITY_CALLBACK = 104;
    public static final int MESSAGE_SHOW_MENU = 107;

    public static final int MENU_STATE_NONE = 0;
    public static final int MENU_STATE_CLOSE = 1;
    public static final int MENU_STATE_FULL = 2;

    // The duration to wait before we consider the start activity as having timed out
    private static final long START_ACTIVITY_REQUEST_TIMEOUT_MS = 300;

    /**
     * A listener interface to receive notification on changes in PIP.
     */
    public interface Listener {
        /**
         * Called when the PIP menu visibility changes.
         *
         * @param menuState the current state of the menu
         * @param resize whether or not to resize the PiP with the state change
         */
        void onPipMenuStateChanged(int menuState, boolean resize);

        /**
         * Called when the PIP requested to be expanded.
         */
        void onPipExpand();

        /**
         * Called when the PIP requested to be dismissed.
         */
        void onPipDismiss();

        /**
         * Called when the PIP requested to show the menu.
         */
        void onPipShowMenu();
    }

    private Context mContext;
    private PipMediaController mMediaController;
    private InputConsumerController mInputConsumerController;

    private ArrayList<Listener> mListeners = new ArrayList<>();
    private ParceledListSlice mAppActions;
    private ParceledListSlice mMediaActions;
    private int mMenuState;

    // The dismiss fraction update is sent frequently, so use a temporary bundle for the message
    private Bundle mTmpDismissFractionData = new Bundle();

    private Runnable mOnAnimationEndRunnable;
    private boolean mStartActivityRequested;
    private long mStartActivityRequestedTime;
    private Messenger mToActivityMessenger;
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MESSAGE_MENU_STATE_CHANGED: {
                    int menuState = msg.arg1;
                    boolean resize = msg.arg2 != 0;
                    onMenuStateChanged(menuState, resize);
                    break;
                }
                case MESSAGE_EXPAND_PIP: {
                    mListeners.forEach(l -> l.onPipExpand());
                    break;
                }
                case MESSAGE_DISMISS_PIP: {
                    mListeners.forEach(l -> l.onPipDismiss());
                    break;
                }
                case MESSAGE_SHOW_MENU: {
                    mListeners.forEach(l -> l.onPipShowMenu());
                    break;
                }
                case MESSAGE_UPDATE_ACTIVITY_CALLBACK: {
                    mToActivityMessenger = msg.replyTo;
                    setStartActivityRequested(false);
                    if (mOnAnimationEndRunnable != null) {
                        mOnAnimationEndRunnable.run();
                        mOnAnimationEndRunnable = null;
                    }
                    // Mark the menu as invisible once the activity finishes as well
                    if (mToActivityMessenger == null) {
                        final boolean resize = msg.arg1 != 0;
                        onMenuStateChanged(MENU_STATE_NONE, resize);
                    }
                    break;
                }
            }
        }
    };
    private Messenger mMessenger = new Messenger(mHandler);

    private Runnable mStartActivityRequestedTimeoutRunnable = () -> {
        setStartActivityRequested(false);
        if (mOnAnimationEndRunnable != null) {
            mOnAnimationEndRunnable.run();
            mOnAnimationEndRunnable = null;
        }
        Log.e(TAG, "Expected start menu activity request timed out");
    };

    private ActionListener mMediaActionListener = new ActionListener() {
        @Override
        public void onMediaActionsChanged(List<RemoteAction> mediaActions) {
            mMediaActions = new ParceledListSlice<>(mediaActions);
            updateMenuActions();
        }
    };

    public PipMenuActivityController(Context context,
            PipMediaController mediaController, InputConsumerController inputConsumerController) {
        mContext = context;
        mMediaController = mediaController;
        mInputConsumerController = inputConsumerController;
    }

    public boolean isMenuActivityVisible() {
        return mToActivityMessenger != null;
    }

    public void onActivityPinned() {
        mInputConsumerController.registerInputConsumer();
    }

    public void onActivityUnpinned() {
        hideMenu();
        mInputConsumerController.unregisterInputConsumer();
        setStartActivityRequested(false);
    }

    public void onPinnedStackAnimationEnded() {
        // Note: Only active menu activities care about this event
        if (mToActivityMessenger != null) {
            Message m = Message.obtain();
            m.what = PipMenuActivity.MESSAGE_ANIMATION_ENDED;
            try {
                mToActivityMessenger.send(m);
            } catch (RemoteException e) {
                Log.e(TAG, "Could not notify menu pinned animation ended", e);
            }
        }
    }

    /**
     * Adds a new menu activity listener.
     */
    public void addListener(Listener listener) {
        if (!mListeners.contains(listener)) {
            mListeners.add(listener);
        }
    }

    /**
     * Updates the appearance of the menu and scrim on top of the PiP while dismissing.
     */
    public void setDismissFraction(float fraction) {
        if (DEBUG) {
            Log.d(TAG, "setDismissFraction() hasActivity=" + (mToActivityMessenger != null)
                    + " fraction=" + fraction);
        }
        if (mToActivityMessenger != null) {
            mTmpDismissFractionData.clear();
            mTmpDismissFractionData.putFloat(EXTRA_DISMISS_FRACTION, fraction);
            Message m = Message.obtain();
            m.what = PipMenuActivity.MESSAGE_UPDATE_DISMISS_FRACTION;
            m.obj = mTmpDismissFractionData;
            try {
                mToActivityMessenger.send(m);
            } catch (RemoteException e) {
                Log.e(TAG, "Could not notify menu to update dismiss fraction", e);
            }
        } else if (!mStartActivityRequested || isStartActivityRequestedElapsed()) {
            // If we haven't requested the start activity, or if it previously took too long to
            // start, then start it
            startMenuActivity(MENU_STATE_NONE, null /* stackBounds */,
                    null /* movementBounds */, false /* allowMenuTimeout */,
                    false /* resizeMenuOnShow */);
        }
    }

    /**
     * Shows the menu activity.
     */
    public void showMenu(int menuState, Rect stackBounds, Rect movementBounds,
            boolean allowMenuTimeout, boolean willResizeMenu) {
        if (DEBUG) {
            Log.d(TAG, "showMenu() state=" + menuState
                    + " hasActivity=" + (mToActivityMessenger != null)
                    + " callers=\n" + Debug.getCallers(5, "    "));
        }

        if (mToActivityMessenger != null) {
            Bundle data = new Bundle();
            data.putInt(EXTRA_MENU_STATE, menuState);
            if (stackBounds != null) {
                data.putParcelable(EXTRA_STACK_BOUNDS, stackBounds);
            }
            data.putParcelable(EXTRA_MOVEMENT_BOUNDS, movementBounds);
            data.putBoolean(EXTRA_ALLOW_TIMEOUT, allowMenuTimeout);
            data.putBoolean(EXTRA_WILL_RESIZE_MENU, willResizeMenu);
            Message m = Message.obtain();
            m.what = PipMenuActivity.MESSAGE_SHOW_MENU;
            m.obj = data;
            try {
                mToActivityMessenger.send(m);
            } catch (RemoteException e) {
                Log.e(TAG, "Could not notify menu to show", e);
            }
        } else if (!mStartActivityRequested || isStartActivityRequestedElapsed()) {
            // If we haven't requested the start activity, or if it previously took too long to
            // start, then start it
            startMenuActivity(menuState, stackBounds, movementBounds, allowMenuTimeout,
                    willResizeMenu);
        }
    }

    /**
     * Pokes the menu, indicating that the user is interacting with it.
     */
    public void pokeMenu() {
        if (DEBUG) {
            Log.d(TAG, "pokeMenu() hasActivity=" + (mToActivityMessenger != null));
        }
        if (mToActivityMessenger != null) {
            Message m = Message.obtain();
            m.what = PipMenuActivity.MESSAGE_POKE_MENU;
            try {
                mToActivityMessenger.send(m);
            } catch (RemoteException e) {
                Log.e(TAG, "Could not notify poke menu", e);
            }
        }
    }

    /**
     * Hides the menu activity.
     */
    public void hideMenu() {
        if (DEBUG) {
            Log.d(TAG, "hideMenu() state=" + mMenuState
                    + " hasActivity=" + (mToActivityMessenger != null)
                    + " callers=\n" + Debug.getCallers(5, "    "));
        }
        if (mToActivityMessenger != null) {
            Message m = Message.obtain();
            m.what = PipMenuActivity.MESSAGE_HIDE_MENU;
            try {
                mToActivityMessenger.send(m);
            } catch (RemoteException e) {
                Log.e(TAG, "Could not notify menu to hide", e);
            }
        }
    }

    /**
     * Hides the menu activity.
     */
    public void hideMenu(Runnable onStartCallback, Runnable onEndCallback) {
        if (mStartActivityRequested) {
            // If the menu has been start-requested, but not actually started, then we defer the
            // trigger callback until the menu has started and called back to the controller.
            mOnAnimationEndRunnable = onEndCallback;
            onStartCallback.run();

            // Fallback for b/63752800, we have started the PipMenuActivity but it has not made any
            // callbacks. Don't continue to wait for the menu to show past some timeout.
            mHandler.removeCallbacks(mStartActivityRequestedTimeoutRunnable);
            mHandler.postDelayed(mStartActivityRequestedTimeoutRunnable,
                    START_ACTIVITY_REQUEST_TIMEOUT_MS);
        } else if (mMenuState != MENU_STATE_NONE && mToActivityMessenger != null) {
            // If the menu is visible in either the closed or full state, then hide the menu and
            // trigger the animation trigger afterwards
            onStartCallback.run();
            Message m = Message.obtain();
            m.what = PipMenuActivity.MESSAGE_HIDE_MENU;
            m.obj = onEndCallback;
            try {
                mToActivityMessenger.send(m);
            } catch (RemoteException e) {
                Log.e(TAG, "Could not notify hide menu", e);
            }
        }
    }

    /**
     * Preemptively mark the menu as invisible, used when we are directly manipulating the pinned
     * stack and don't want to trigger a resize which can animate the stack in a conflicting way
     * (ie. when manually expanding or dismissing).
     */
    public void hideMenuWithoutResize() {
        onMenuStateChanged(MENU_STATE_NONE, false /* resize */);
    }

    /**
     * Sets the menu actions to the actions provided by the current PiP activity.
     */
    public void setAppActions(ParceledListSlice appActions) {
        mAppActions = appActions;
        updateMenuActions();
    }

    /**
     * @return the best set of actions to show in the PiP menu.
     */
    private ParceledListSlice resolveMenuActions() {
        if (isValidActions(mAppActions)) {
            return mAppActions;
        }
        return mMediaActions;
    }

    /**
     * Starts the menu activity on the top task of the pinned stack.
     */
    private void startMenuActivity(int menuState, Rect stackBounds, Rect movementBounds,
            boolean allowMenuTimeout, boolean willResizeMenu) {
        try {
            StackInfo pinnedStackInfo = ActivityTaskManager.getService().getStackInfo(
                    WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
            if (pinnedStackInfo != null && pinnedStackInfo.taskIds != null &&
                    pinnedStackInfo.taskIds.length > 0) {
                Intent intent = new Intent(mContext, PipMenuActivity.class);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                intent.putExtra(EXTRA_CONTROLLER_MESSENGER, mMessenger);
                intent.putExtra(EXTRA_ACTIONS, resolveMenuActions());
                if (stackBounds != null) {
                    intent.putExtra(EXTRA_STACK_BOUNDS, stackBounds);
                }
                if (movementBounds != null) {
                    intent.putExtra(EXTRA_MOVEMENT_BOUNDS, movementBounds);
                }
                intent.putExtra(EXTRA_MENU_STATE, menuState);
                intent.putExtra(EXTRA_ALLOW_TIMEOUT, allowMenuTimeout);
                intent.putExtra(EXTRA_WILL_RESIZE_MENU, willResizeMenu);
                ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
                options.setLaunchTaskId(
                        pinnedStackInfo.taskIds[pinnedStackInfo.taskIds.length - 1]);
                options.setTaskOverlay(true, true /* canResume */);
                mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
                setStartActivityRequested(true);
            } else {
                Log.e(TAG, "No PIP tasks found");
            }
        } catch (RemoteException e) {
            setStartActivityRequested(false);
            Log.e(TAG, "Error showing PIP menu activity", e);
        }
    }

    /**
     * Updates the PiP menu activity with the best set of actions provided.
     */
    private void updateMenuActions() {
        if (mToActivityMessenger != null) {
            // Fetch the pinned stack bounds
            Rect stackBounds = null;
            try {
                StackInfo pinnedStackInfo = ActivityTaskManager.getService().getStackInfo(
                        WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
                if (pinnedStackInfo != null) {
                    stackBounds = pinnedStackInfo.bounds;
                }
            } catch (RemoteException e) {
                Log.e(TAG, "Error showing PIP menu activity", e);
            }

            Bundle data = new Bundle();
            data.putParcelable(EXTRA_STACK_BOUNDS, stackBounds);
            data.putParcelable(EXTRA_ACTIONS, resolveMenuActions());
            Message m = Message.obtain();
            m.what = PipMenuActivity.MESSAGE_UPDATE_ACTIONS;
            m.obj = data;
            try {
                mToActivityMessenger.send(m);
            } catch (RemoteException e) {
                Log.e(TAG, "Could not notify menu activity to update actions", e);
            }
        }
    }

    /**
     * Returns whether the set of actions are valid.
     */
    private boolean isValidActions(ParceledListSlice actions) {
        return actions != null && actions.getList().size() > 0;
    }

    /**
     * @return whether the time of the activity request has exceeded the timeout.
     */
    private boolean isStartActivityRequestedElapsed() {
        return (SystemClock.uptimeMillis() - mStartActivityRequestedTime)
                >= START_ACTIVITY_REQUEST_TIMEOUT_MS;
    }

    /**
     * Handles changes in menu visibility.
     */
    private void onMenuStateChanged(int menuState, boolean resize) {
        if (DEBUG) {
            Log.d(TAG, "onMenuStateChanged() mMenuState=" + mMenuState
                    + " menuState=" + menuState + " resize=" + resize);
        }

        if (menuState != mMenuState) {
            mListeners.forEach(l -> l.onPipMenuStateChanged(menuState, resize));
            if (menuState == MENU_STATE_FULL) {
                // Once visible, start listening for media action changes. This call will trigger
                // the menu actions to be updated again.
                mMediaController.addListener(mMediaActionListener);
            } else {
                // Once hidden, stop listening for media action changes. This call will trigger
                // the menu actions to be updated again.
                mMediaController.removeListener(mMediaActionListener);
            }
        }
        mMenuState = menuState;
    }

    private void setStartActivityRequested(boolean requested) {
        mHandler.removeCallbacks(mStartActivityRequestedTimeoutRunnable);
        mStartActivityRequested = requested;
        mStartActivityRequestedTime = requested ? SystemClock.uptimeMillis() : 0;
    }

    /**
     * Handles a pointer event sent from pip input consumer.
     */
    void handlePointerEvent(MotionEvent ev) {
        if (mToActivityMessenger != null) {
            Message m = Message.obtain();
            m.what = PipMenuActivity.MESSAGE_POINTER_EVENT;
            m.obj = ev;
            try {
                mToActivityMessenger.send(m);
            } catch (RemoteException e) {
                Log.e(TAG, "Could not dispatch touch event", e);
            }
        }
    }

    public void dump(PrintWriter pw, String prefix) {
        final String innerPrefix = prefix + "  ";
        pw.println(prefix + TAG);
        pw.println(innerPrefix + "mMenuState=" + mMenuState);
        pw.println(innerPrefix + "mToActivityMessenger=" + mToActivityMessenger);
        pw.println(innerPrefix + "mListeners=" + mListeners.size());
        pw.println(innerPrefix + "mStartActivityRequested=" + mStartActivityRequested);
        pw.println(innerPrefix + "mStartActivityRequestedTime=" + mStartActivityRequestedTime);
    }
}
