/*
 * 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.recents.tv;

import android.app.Activity;
import android.app.ActivityOptions;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.UserHandle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewTreeObserver.OnPreDrawListener;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.widget.FrameLayout.LayoutParams;

import com.android.systemui.R;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsActivityLaunchState;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.RecentsImpl;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
import com.android.systemui.recents.events.activity.HideRecentsEvent;
import com.android.systemui.recents.events.activity.LaunchTaskFailedEvent;
import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;
import com.android.systemui.recents.events.ui.UserInteractionEvent;
import com.android.systemui.recents.events.ui.focus.DismissFocusedTaskViewEvent;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.model.RecentsPackageMonitor;
import com.android.systemui.recents.model.RecentsTaskLoadPlan;
import com.android.systemui.recents.model.RecentsTaskLoader;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
import com.android.systemui.recents.tv.animations.HomeRecentsEnterExitAnimationHolder;
import com.android.systemui.recents.tv.views.RecentsTvView;
import com.android.systemui.recents.tv.views.TaskCardView;
import com.android.systemui.recents.tv.views.TaskStackHorizontalGridView;
import com.android.systemui.recents.tv.views.TaskStackHorizontalViewAdapter;
import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.tv.pip.PipManager;
import com.android.systemui.tv.pip.PipRecentsOverlayManager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * The main TV recents activity started by the RecentsImpl.
 */
public class RecentsTvActivity extends Activity implements OnPreDrawListener {
    private final static String TAG = "RecentsTvActivity";
    private final static boolean DEBUG = false;

    public final static int EVENT_BUS_PRIORITY = Recents.EVENT_BUS_PRIORITY + 1;
    private final static String RECENTS_HOME_INTENT_EXTRA =
            "com.android.systemui.recents.tv.RecentsTvActivity.RECENTS_HOME_INTENT_EXTRA";

    private boolean mFinishedOnStartup;
    private RecentsPackageMonitor mPackageMonitor;
    private long mLastTabKeyEventTime;
    private boolean mIgnoreAltTabRelease;
    private boolean mLaunchedFromHome;

    private RecentsTvView mRecentsView;
    private View mPipView;
    private TaskStackHorizontalViewAdapter mTaskStackViewAdapter;
    private TaskStackHorizontalGridView mTaskStackHorizontalGridView;
    private FinishRecentsRunnable mFinishLaunchHomeRunnable;
    private HomeRecentsEnterExitAnimationHolder mHomeRecentsEnterExitAnimationHolder;

    private final PipManager mPipManager = PipManager.getInstance();
    private final PipManager.Listener mPipListener = new PipManager.Listener() {
        @Override
        public void onPipEntered() {
            updatePipUI();
        }

        @Override
        public void onPipActivityClosed() {
            updatePipUI();
        }

        @Override
        public void onShowPipMenu() {
            updatePipUI();
        }

        @Override
        public void onMoveToFullscreen() {
            // Recents should be dismissed when PIP moves to fullscreen. If not, Recents will
            // be unnecessarily shown in the scenario: PIP->Fullscreen->PIP.
            // Do not show Recents close animation because PIP->Fullscreen animation will be shown
            // instead.
            dismissRecentsToLaunchTargetTaskOrHome(false);
        }

        @Override
        public void onPipResizeAboutToStart() { }
    };
    private PipRecentsOverlayManager mPipRecentsOverlayManager;
    private final PipRecentsOverlayManager.Callback mPipRecentsOverlayManagerCallback =
            new PipRecentsOverlayManager.Callback() {
                @Override
                public void onClosed() {
                    dismissRecentsToLaunchTargetTaskOrHome(true);
                }

                @Override
                public void onBackPressed() {
                    RecentsTvActivity.this.onBackPressed();
                }

                @Override
                public void onRecentsFocused() {
                    mRecentsView.requestFocus();
                    mRecentsView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
                }
            };
    private final View.OnFocusChangeListener mPipViewFocusChangeListener =
            new View.OnFocusChangeListener() {
                @Override
                public void onFocusChange(View v, boolean hasFocus) {
                    handlePipViewFocusChange(hasFocus);
                }
            };

    /**
     * A common Runnable to finish Recents by launching Home with an animation depending on the
     * last activity launch state.  Generally we always launch home when we exit Recents rather than
     * just finishing the activity since we don't know what is behind Recents in the task stack.
     */
    class FinishRecentsRunnable implements Runnable {
        Intent mLaunchIntent;

        /**
         * Creates a finish runnable that starts the specified intent.
         */
        public FinishRecentsRunnable(Intent launchIntent) {
            mLaunchIntent = launchIntent;
        }

        @Override
        public void run() {
            try {
                ActivityOptions opts = ActivityOptions.makeCustomAnimation(RecentsTvActivity.this,
                        R.anim.recents_to_launcher_enter, R.anim.recents_to_launcher_exit);
                startActivityAsUser(mLaunchIntent, opts.toBundle(), UserHandle.CURRENT);
            } catch (Exception e) {
                Log.e(TAG, getString(R.string.recents_launch_error_message, "Home"), e);
            }
        }
    }

    private void updateRecentsTasks() {
        RecentsTaskLoader loader = Recents.getTaskLoader();
        RecentsTaskLoadPlan plan = RecentsImpl.consumeInstanceLoadPlan();
        if (plan == null) {
            plan = loader.createLoadPlan(this);
        }

        RecentsConfiguration config = Recents.getConfiguration();
        RecentsActivityLaunchState launchState = config.getLaunchState();
        if (!plan.hasTasks()) {
            loader.preloadTasks(plan, -1, !launchState.launchedFromHome);
        }

        int numVisibleTasks = TaskCardView.getNumberOfVisibleTasks(getApplicationContext());
        mLaunchedFromHome = launchState.launchedFromHome;
        TaskStack stack = plan.getTaskStack();
        RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
        loadOpts.runningTaskId = launchState.launchedToTaskId;
        loadOpts.numVisibleTasks = numVisibleTasks;
        loadOpts.numVisibleTaskThumbnails = numVisibleTasks;
        loader.loadTasks(this, plan, loadOpts);


        mRecentsView.setTaskStack(stack);
        List stackTasks = stack.getStackTasks();
        Collections.reverse(stackTasks);
        if (mTaskStackViewAdapter == null) {
            mTaskStackViewAdapter = new TaskStackHorizontalViewAdapter(stackTasks);
            mTaskStackHorizontalGridView = mRecentsView
                    .setTaskStackViewAdapter(mTaskStackViewAdapter);
        } else {
            mTaskStackViewAdapter.setNewStackTasks(stackTasks);
        }

        if (launchState.launchedToTaskId != -1) {
            ArrayList<Task> tasks = stack.getStackTasks();
            int taskCount = tasks.size();
            for (int i = 0; i < taskCount; i++) {
                Task t = tasks.get(i);
                if (t.key.id == launchState.launchedToTaskId) {
                    t.isLaunchTarget = true;
                    break;
                }
            }
        }
    }

    boolean dismissRecentsToLaunchTargetTaskOrHome(boolean animate) {
        SystemServicesProxy ssp = Recents.getSystemServices();
        if (ssp.isRecentsActivityVisible()) {
            // If we have a focused Task, launch that Task now
            if (mRecentsView.launchPreviousTask(animate)) {
              return true;
            }
            // If none of the other cases apply, then just go Home
            dismissRecentsToHome(animate /* animateTaskViews */);
        }
        return false;
    }

    boolean dismissRecentsToFocusedTaskOrHome() {
        SystemServicesProxy ssp = Recents.getSystemServices();
        if (ssp.isRecentsActivityVisible()) {
            // If we have a focused Task, launch that Task now
            if (mRecentsView.launchFocusedTask()) return true;
            // If none of the other cases apply, then just go Home
            dismissRecentsToHome(true /* animateTaskViews */);
            return true;
        }
        return false;
    }

    void dismissRecentsToHome(boolean animateTaskViews) {
        Runnable closeSystemWindows = new Runnable() {
            @Override
            public void run() {
                Recents.getSystemServices().sendCloseSystemWindows(
                        BaseStatusBar.SYSTEM_DIALOG_REASON_HOME_KEY);
            }
        };
        DismissRecentsToHomeAnimationStarted dismissEvent =
                new DismissRecentsToHomeAnimationStarted(animateTaskViews);
        dismissEvent.addPostAnimationCallback(mFinishLaunchHomeRunnable);
        dismissEvent.addPostAnimationCallback(closeSystemWindows);

        if (mTaskStackHorizontalGridView.getChildCount() > 0 && animateTaskViews) {
            mHomeRecentsEnterExitAnimationHolder.startExitAnimation(dismissEvent);
        } else {
            closeSystemWindows.run();
            mFinishLaunchHomeRunnable.run();
        }
    }

    boolean dismissRecentsToHomeIfVisible(boolean animated) {
        SystemServicesProxy ssp = Recents.getSystemServices();
        if (ssp.isRecentsActivityVisible()) {
            // Return to Home
            dismissRecentsToHome(animated);
            return true;
        }
        return false;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mFinishedOnStartup = false;

        // In the case that the activity starts up before the Recents component has initialized
        // (usually when debugging/pushing the SysUI apk), just finish this activity.
        SystemServicesProxy ssp = Recents.getSystemServices();
        if (ssp == null) {
            mFinishedOnStartup = true;
            finish();
            return;
        }
        mPipRecentsOverlayManager = PipManager.getInstance().getPipRecentsOverlayManager();

        // Register this activity with the event bus
        EventBus.getDefault().register(this, EVENT_BUS_PRIORITY);

        mPackageMonitor = new RecentsPackageMonitor();
        mPackageMonitor.register(this);

        // Set the Recents layout
        setContentView(R.layout.recents_on_tv);

        mRecentsView = (RecentsTvView) findViewById(R.id.recents_view);
        mRecentsView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
                View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);

        mPipView = findViewById(R.id.pip);
        // Place mPipView at the PIP bounds for fine tuned focus handling.
        Rect pipBounds = mPipManager.getRecentsFocusedPipBounds();
        LayoutParams lp = (LayoutParams) mPipView.getLayoutParams();
        lp.width = pipBounds.width();
        lp.height = pipBounds.height();
        lp.leftMargin = pipBounds.left;
        lp.topMargin = pipBounds.top;
        mPipView.setLayoutParams(lp);

        mPipRecentsOverlayManager.setCallback(mPipRecentsOverlayManagerCallback);

        getWindow().getAttributes().privateFlags |=
                WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;

        // Create the home intent runnable
        Intent homeIntent = new Intent(Intent.ACTION_MAIN, null);
        homeIntent.addCategory(Intent.CATEGORY_HOME);
        homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
                Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
        homeIntent.putExtra(RECENTS_HOME_INTENT_EXTRA, true);
        mFinishLaunchHomeRunnable = new FinishRecentsRunnable(homeIntent);

        mPipManager.addListener(mPipListener);
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
    }

    @Override
    public void onEnterAnimationComplete() {
        super.onEnterAnimationComplete();
        if(mLaunchedFromHome) {
            mHomeRecentsEnterExitAnimationHolder.startEnterAnimation(mPipManager.isPipShown());
        }
        mTaskStackViewAdapter.setResetAddedCards(true);
        EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
    }

    @Override
    public void onResume() {
        super.onResume();
        mPipRecentsOverlayManager.onRecentsResumed();
        // Update the recent tasks
        updateRecentsTasks();

        mHomeRecentsEnterExitAnimationHolder = new HomeRecentsEnterExitAnimationHolder(
                getApplicationContext(), mTaskStackHorizontalGridView);
        if(mTaskStackHorizontalGridView != null &&
                mTaskStackHorizontalGridView.getChildCount() > 0) {
            if(mLaunchedFromHome) {
                mHomeRecentsEnterExitAnimationHolder.setEnterFromHomeStartingAnimationValues();
            } else {
                mHomeRecentsEnterExitAnimationHolder.setEnterFromAppStartingAnimationValues();
            }
        } else {
            mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
        }

        // If this is a new instance from a configuration change, then we have to manually trigger
        // the enter animation state, or if recents was relaunched by AM, without going through
        // the normal mechanisms
        RecentsConfiguration config = Recents.getConfiguration();
        RecentsActivityLaunchState launchState = config.getLaunchState();
        boolean wasLaunchedByAm = !launchState.launchedFromHome &&
                !launchState.launchedFromApp;
        if (wasLaunchedByAm) {
            EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
        }

        // Notify that recents is now visible
        SystemServicesProxy ssp = Recents.getSystemServices();
        EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, true));
        if(mTaskStackHorizontalGridView.getStack().getTaskCount() > 1 && !mLaunchedFromHome) {
            // If there are 2 or more tasks, and we are not launching from home
            // set the selected position to the 2nd task to allow for faster app switching
            mTaskStackHorizontalGridView.setSelectedPosition(1);
        } else {
            mTaskStackHorizontalGridView.setSelectedPosition(0);
        }

        updatePipUI();
    }

    @Override
    public void onPause() {
        super.onPause();
        mPipRecentsOverlayManager.onRecentsPaused();
        mTaskStackViewAdapter.setResetAddedCards(false);
    }

    @Override
    protected void onStop() {
        super.onStop();

        mIgnoreAltTabRelease = false;
        // Notify that recents is now hidden
        EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, false));

        // Workaround for b/22542869, if the RecentsActivity is started again, but without going
        // through SystemUI, we need to reset the config launch flags to ensure that we do not
        // wait on the system to send a signal that was never queued.
        RecentsConfiguration config = Recents.getConfiguration();
        RecentsActivityLaunchState launchState = config.getLaunchState();
        launchState.reset();

        // Workaround for b/28333917.
        finish();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        mPipManager.removeListener(mPipListener);
        // In the case that the activity finished on startup, just skip the unregistration below
        if (mFinishedOnStartup) {
            return;
        }

        // Unregister any broadcast receivers for the task loader
        mPackageMonitor.unregister();

        EventBus.getDefault().unregister(this);
    }

    @Override
    public void onTrimMemory(int level) {
        RecentsTaskLoader loader = Recents.getTaskLoader();
        if (loader != null) {
            loader.onTrimMemory(level);
        }
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        switch (keyCode) {
            case KeyEvent.KEYCODE_DEL:
            case KeyEvent.KEYCODE_FORWARD_DEL: {
                EventBus.getDefault().send(new DismissFocusedTaskViewEvent());
                return true;
            }
            default:
                break;
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public void onUserInteraction() {
        EventBus.getDefault().send(new UserInteractionEvent());
    }

    @Override
    public void onBackPressed() {
        // Back behaves like the recents button so just trigger a toggle event
        EventBus.getDefault().send(new ToggleRecentsEvent());
    }

    /**** EventBus events ****/

    public final void onBusEvent(ToggleRecentsEvent event) {
        RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
        if (launchState.launchedFromHome) {
            dismissRecentsToHome(true /* animateTaskViews */);
        } else {
            dismissRecentsToLaunchTargetTaskOrHome(true);
        }
    }

    public final void onBusEvent(HideRecentsEvent event) {
        if (event.triggeredFromAltTab) {
            // If we are hiding from releasing Alt-Tab, dismiss Recents to the focused app
            if (!mIgnoreAltTabRelease) {
                dismissRecentsToFocusedTaskOrHome();
            }
        } else if (event.triggeredFromHomeKey) {
                dismissRecentsToHome(true /* animateTaskViews */);
        } else {
            // Do nothing
        }
    }

    public final void onBusEvent(CancelEnterRecentsWindowAnimationEvent event) {
        RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
        int launchToTaskId = launchState.launchedToTaskId;
        if (launchToTaskId != -1 &&
                (event.launchTask == null || launchToTaskId != event.launchTask.key.id)) {
            SystemServicesProxy ssp = Recents.getSystemServices();
            ssp.cancelWindowTransition(launchState.launchedToTaskId);
            ssp.cancelThumbnailTransition(getTaskId());
        }
    }

    public final void onBusEvent(DeleteTaskDataEvent event) {
        // Remove any stored data from the loader
        RecentsTaskLoader loader = Recents.getTaskLoader();
        loader.deleteTaskData(event.task, false);

        // Remove the task from activity manager
        SystemServicesProxy ssp = Recents.getSystemServices();
        ssp.removeTask(event.task.key.id);
    }

    public final void onBusEvent(AllTaskViewsDismissedEvent event) {
        if (mPipManager.isPipShown()) {
            mRecentsView.showEmptyView();
        } else {
            dismissRecentsToHome(false);
        }
    }

    public final void onBusEvent(LaunchTaskFailedEvent event) {
        // Return to Home
        dismissRecentsToHome(true /* animateTaskViews */);
    }

    @Override
    public boolean onPreDraw() {
        mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this);
        if(mLaunchedFromHome) {
            mHomeRecentsEnterExitAnimationHolder.setEnterFromHomeStartingAnimationValues();
        } else {
            mHomeRecentsEnterExitAnimationHolder.setEnterFromAppStartingAnimationValues();
        }
        // We post to make sure that this information is delivered after this traversals is
        // finished.
        mRecentsView.post(new Runnable() {
            @Override
            public void run() {
                Recents.getSystemServices().endProlongedAnimations();
            }
        });
        return true;
    }

    private void updatePipUI() {
        if (mPipManager.isPipShown()) {
            mPipView.setVisibility(View.VISIBLE);
            mPipView.setOnFocusChangeListener(mPipViewFocusChangeListener);
            if (mPipView.hasFocus()) {
                // This can happen only if the activity is resumed. Ask for reset.
                handlePipViewFocusChange(true);
            } else {
                mPipView.requestFocus();
            }
        } else {
            mPipView.setVisibility(View.GONE);
            mPipRecentsOverlayManager.removePipRecentsOverlayView();
        }
    }

    /**
     * Handles the PIP view's focus change.
     * This starts the relevant recents row animation
     * and give focus to the recents overlay if needed.
     */
    private void handlePipViewFocusChange(boolean hasFocus) {
        mRecentsView.startRecentsRowFocusAnimation(!hasFocus);
        if (hasFocus) {
            // When PIP view has focus, recents overlay view will takes the focus
            // as if it's the part of the Recents UI.
            mPipRecentsOverlayManager.requestFocus(
                    mTaskStackViewAdapter.getItemCount() > 0);
        } else {
            mPipRecentsOverlayManager.clearFocus();
        }
    }
}
