/*
 * Copyright (C) 2019 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.assist;

import static com.android.systemui.assist.AssistModule.ASSIST_HANDLE_THREAD_NAME;
import static com.android.systemui.assist.AssistModule.UPTIME_NAME;

import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ResolveInfo;
import android.os.Handler;
import android.provider.Settings;

import androidx.annotation.Nullable;
import androidx.slice.Clock;

import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.systemui.assist.AssistHandleBehaviorController.BehaviorController;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.model.SysUiState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.PackageManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.statusbar.StatusBarState;

import java.io.PrintWriter;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;

import dagger.Lazy;

/**
 * Assistant handle behavior that hides the handles when the phone is dozing or in immersive mode,
 * shows the handles when on lockscreen, and shows the handles temporarily when changing tasks or
 * entering overview.
 */
@Singleton
final class AssistHandleReminderExpBehavior implements BehaviorController {

    private static final String LEARNING_TIME_ELAPSED_KEY = "reminder_exp_learning_time_elapsed";
    private static final String LEARNING_EVENT_COUNT_KEY = "reminder_exp_learning_event_count";
    private static final String LEARNED_HINT_LAST_SHOWN_KEY =
            "reminder_exp_learned_hint_last_shown";
    private static final long DEFAULT_LEARNING_TIME_MS = TimeUnit.DAYS.toMillis(10);
    private static final int DEFAULT_LEARNING_COUNT = 10;
    private static final long DEFAULT_SHOW_AND_GO_DELAYED_SHORT_DELAY_MS = 150;
    private static final long DEFAULT_SHOW_AND_GO_DELAYED_LONG_DELAY_MS =
            TimeUnit.SECONDS.toMillis(1);
    private static final long DEFAULT_SHOW_AND_GO_DELAY_RESET_TIMEOUT_MS =
            TimeUnit.SECONDS.toMillis(3);
    private static final boolean DEFAULT_SUPPRESS_ON_LOCKSCREEN = false;
    private static final boolean DEFAULT_SUPPRESS_ON_LAUNCHER = false;
    private static final boolean DEFAULT_SUPPRESS_ON_APPS = true;
    private static final boolean DEFAULT_SHOW_WHEN_TAUGHT = false;

    private static final String[] DEFAULT_HOME_CHANGE_ACTIONS = new String[] {
            PackageManagerWrapper.ACTION_PREFERRED_ACTIVITY_CHANGED,
            Intent.ACTION_BOOT_COMPLETED,
            Intent.ACTION_PACKAGE_ADDED,
            Intent.ACTION_PACKAGE_CHANGED,
            Intent.ACTION_PACKAGE_REMOVED
    };

    private final StatusBarStateController.StateListener mStatusBarStateListener =
            new StatusBarStateController.StateListener() {
                @Override
                public void onStateChanged(int newState) {
                    handleStatusBarStateChanged(newState);
                }

                @Override
                public void onDozingChanged(boolean isDozing) {
                    handleDozingChanged(isDozing);
                }
            };
    private final TaskStackChangeListener mTaskStackChangeListener =
            new TaskStackChangeListener() {
                @Override
                public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo) {
                    handleTaskStackTopChanged(taskInfo.taskId, taskInfo.topActivity);
                }

                @Override
                public void onTaskCreated(int taskId, ComponentName componentName) {
                    handleTaskStackTopChanged(taskId, componentName);
                }
            };
    private final OverviewProxyService.OverviewProxyListener mOverviewProxyListener =
            new OverviewProxyService.OverviewProxyListener() {
                @Override
                public void onOverviewShown(boolean fromHome) {
                    handleOverviewShown();
                }
            };
    private final SysUiState.SysUiStateCallback mSysUiStateCallback =
            this::handleSystemUiStateChanged;
    private final WakefulnessLifecycle.Observer mWakefulnessLifecycleObserver =
            new WakefulnessLifecycle.Observer() {
                @Override
                public void onStartedWakingUp() {
                    handleWakefullnessChanged(/* isAwake = */ false);
                }

                @Override
                public void onFinishedWakingUp() {
                    handleWakefullnessChanged(/* isAwake = */ true);
                }

                @Override
                public void onStartedGoingToSleep() {
                    handleWakefullnessChanged(/* isAwake = */ false);
                }

                @Override
                public void onFinishedGoingToSleep() {
                    handleWakefullnessChanged(/* isAwake = */ false);
                }
            };
    private final BroadcastReceiver mDefaultHomeBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            mDefaultHome = getCurrentDefaultHome();
        }
    };
    private final IntentFilter mDefaultHomeIntentFilter;
    private final Runnable mResetConsecutiveTaskSwitches = this::resetConsecutiveTaskSwitches;

    private final Clock mClock;
    private final Handler mHandler;
    private final PhenotypeHelper mPhenotypeHelper;
    private final Lazy<StatusBarStateController> mStatusBarStateController;
    private final Lazy<ActivityManagerWrapper> mActivityManagerWrapper;
    private final Lazy<OverviewProxyService> mOverviewProxyService;
    private final Lazy<SysUiState> mSysUiFlagContainer;
    private final Lazy<WakefulnessLifecycle> mWakefulnessLifecycle;
    private final Lazy<PackageManagerWrapper> mPackageManagerWrapper;
    private final Lazy<BroadcastDispatcher> mBroadcastDispatcher;

    private boolean mOnLockscreen;
    private boolean mIsDozing;
    private boolean mIsAwake;
    private int mRunningTaskId;
    private boolean mIsNavBarHidden;
    private boolean mIsLauncherShowing;
    private int mConsecutiveTaskSwitches;

    /** Whether user has learned the gesture. */
    private boolean mIsLearned;
    private long mLastLearningTimestamp;
    /** Uptime while in this behavior. */
    private long mLearningTimeElapsed;
    /** Number of successful Assistant invocations while in this behavior. */
    private int mLearningCount;
    private long mLearnedHintLastShownEpochDay;

    @Nullable private Context mContext;
    @Nullable private AssistHandleCallbacks mAssistHandleCallbacks;
    @Nullable private ComponentName mDefaultHome;

    @Inject
    AssistHandleReminderExpBehavior(
            @Named(UPTIME_NAME) Clock clock,
            @Named(ASSIST_HANDLE_THREAD_NAME) Handler handler,
            PhenotypeHelper phenotypeHelper,
            Lazy<StatusBarStateController> statusBarStateController,
            Lazy<ActivityManagerWrapper> activityManagerWrapper,
            Lazy<OverviewProxyService> overviewProxyService,
            Lazy<SysUiState> sysUiFlagContainer,
            Lazy<WakefulnessLifecycle> wakefulnessLifecycle,
            Lazy<PackageManagerWrapper> packageManagerWrapper,
            Lazy<BroadcastDispatcher> broadcastDispatcher) {
        mClock = clock;
        mHandler = handler;
        mPhenotypeHelper = phenotypeHelper;
        mStatusBarStateController = statusBarStateController;
        mActivityManagerWrapper = activityManagerWrapper;
        mOverviewProxyService = overviewProxyService;
        mSysUiFlagContainer = sysUiFlagContainer;
        mWakefulnessLifecycle = wakefulnessLifecycle;
        mPackageManagerWrapper = packageManagerWrapper;
        mDefaultHomeIntentFilter = new IntentFilter();
        for (String action : DEFAULT_HOME_CHANGE_ACTIONS) {
            mDefaultHomeIntentFilter.addAction(action);
        }
        mBroadcastDispatcher = broadcastDispatcher;
    }

    @Override
    public void onModeActivated(Context context, AssistHandleCallbacks callbacks) {
        mContext = context;
        mAssistHandleCallbacks = callbacks;
        mConsecutiveTaskSwitches = 0;
        mDefaultHome = getCurrentDefaultHome();
        mBroadcastDispatcher.get()
                .registerReceiver(mDefaultHomeBroadcastReceiver, mDefaultHomeIntentFilter);
        mOnLockscreen = onLockscreen(mStatusBarStateController.get().getState());
        mIsDozing = mStatusBarStateController.get().isDozing();
        mStatusBarStateController.get().addCallback(mStatusBarStateListener);
        ActivityManager.RunningTaskInfo runningTaskInfo =
                mActivityManagerWrapper.get().getRunningTask();
        mRunningTaskId = runningTaskInfo == null ? 0 : runningTaskInfo.taskId;
        mActivityManagerWrapper.get().registerTaskStackListener(mTaskStackChangeListener);
        mOverviewProxyService.get().addCallback(mOverviewProxyListener);
        mSysUiFlagContainer.get().addCallback(mSysUiStateCallback);
        mIsAwake = mWakefulnessLifecycle.get().getWakefulness()
                == WakefulnessLifecycle.WAKEFULNESS_AWAKE;
        mWakefulnessLifecycle.get().addObserver(mWakefulnessLifecycleObserver);

        mLearningTimeElapsed = Settings.Secure.getLong(
                context.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, /* default = */ 0);
        mLearningCount = Settings.Secure.getInt(
                context.getContentResolver(), LEARNING_EVENT_COUNT_KEY, /* default = */ 0);
        mLearnedHintLastShownEpochDay = Settings.Secure.getLong(
                context.getContentResolver(), LEARNED_HINT_LAST_SHOWN_KEY, /* default = */ 0);
        mLastLearningTimestamp = mClock.currentTimeMillis();

        callbackForCurrentState(/* justUnlocked = */ false);
    }

    @Override
    public void onModeDeactivated() {
        mAssistHandleCallbacks = null;
        if (mContext != null) {
            mContext.unregisterReceiver(mDefaultHomeBroadcastReceiver);
            Settings.Secure.putLong(mContext.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, 0);
            Settings.Secure.putInt(mContext.getContentResolver(), LEARNING_EVENT_COUNT_KEY, 0);
            Settings.Secure.putLong(mContext.getContentResolver(), LEARNED_HINT_LAST_SHOWN_KEY, 0);
            mContext = null;
        }
        mStatusBarStateController.get().removeCallback(mStatusBarStateListener);
        mActivityManagerWrapper.get().unregisterTaskStackListener(mTaskStackChangeListener);
        mOverviewProxyService.get().removeCallback(mOverviewProxyListener);
        mSysUiFlagContainer.get().removeCallback(mSysUiStateCallback);
        mWakefulnessLifecycle.get().removeObserver(mWakefulnessLifecycleObserver);
    }

    @Override
    public void onAssistantGesturePerformed() {
        if (mContext == null) {
            return;
        }

        Settings.Secure.putLong(
                mContext.getContentResolver(), LEARNING_EVENT_COUNT_KEY, ++mLearningCount);
    }

    @Override
    public void onAssistHandlesRequested() {
        if (mAssistHandleCallbacks != null
                && isFullyAwake()
                && !mIsNavBarHidden
                && !mOnLockscreen) {
            mAssistHandleCallbacks.showAndGo();
        }
    }

    @Nullable
    private ComponentName getCurrentDefaultHome() {
        List<ResolveInfo> homeActivities = new ArrayList<>();
        ComponentName defaultHome = mPackageManagerWrapper.get().getHomeActivities(homeActivities);
        if (defaultHome != null) {
            return defaultHome;
        }

        int topPriority = Integer.MIN_VALUE;
        ComponentName topComponent = null;
        for (ResolveInfo resolveInfo : homeActivities) {
            if (resolveInfo.priority > topPriority) {
                topComponent = resolveInfo.activityInfo.getComponentName();
                topPriority = resolveInfo.priority;
            } else if (resolveInfo.priority == topPriority) {
                topComponent = null;
            }
        }
        return topComponent;
    }

    private void handleStatusBarStateChanged(int newState) {
        boolean onLockscreen = onLockscreen(newState);
        if (mOnLockscreen == onLockscreen) {
            return;
        }

        resetConsecutiveTaskSwitches();
        mOnLockscreen = onLockscreen;
        callbackForCurrentState(!onLockscreen);
    }

    private void handleDozingChanged(boolean isDozing) {
        if (mIsDozing == isDozing) {
            return;
        }

        resetConsecutiveTaskSwitches();
        mIsDozing = isDozing;
        callbackForCurrentState(/* justUnlocked = */ false);
    }

    private void handleWakefullnessChanged(boolean isAwake) {
        if (mIsAwake == isAwake) {
            return;
        }

        resetConsecutiveTaskSwitches();
        mIsAwake = isAwake;
        callbackForCurrentState(/* justUnlocked = */ false);
    }

    private void handleTaskStackTopChanged(int taskId, @Nullable ComponentName taskComponentName) {
        if (mRunningTaskId == taskId || taskComponentName == null) {
            return;
        }

        mRunningTaskId = taskId;
        mIsLauncherShowing = taskComponentName.equals(mDefaultHome);
        if (mIsLauncherShowing) {
            resetConsecutiveTaskSwitches();
        } else {
            rescheduleConsecutiveTaskSwitchesReset();
            mConsecutiveTaskSwitches++;
        }
        callbackForCurrentState(/* justUnlocked = */ false);
    }

    private void handleSystemUiStateChanged(int sysuiStateFlags) {
        boolean isNavBarHidden =
                (sysuiStateFlags & QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN) != 0;
        if (mIsNavBarHidden == isNavBarHidden) {
            return;
        }

        resetConsecutiveTaskSwitches();
        mIsNavBarHidden = isNavBarHidden;
        callbackForCurrentState(/* justUnlocked = */ false);
    }

    private void handleOverviewShown() {
        resetConsecutiveTaskSwitches();
        callbackForCurrentState(/* justUnlocked = */ false);
    }

    private boolean onLockscreen(int statusBarState) {
        return statusBarState == StatusBarState.KEYGUARD
                || statusBarState == StatusBarState.SHADE_LOCKED;
    }

    private void callbackForCurrentState(boolean justUnlocked) {
        updateLearningStatus();

        if (mIsLearned) {
            callbackForLearnedState(justUnlocked);
        } else {
            callbackForUnlearnedState();
        }
    }

    private void callbackForLearnedState(boolean justUnlocked) {
        if (mAssistHandleCallbacks == null) {
            return;
        }

        if (!isFullyAwake() || mIsNavBarHidden || mOnLockscreen || !getShowWhenTaught()) {
            mAssistHandleCallbacks.hide();
        } else if (justUnlocked) {
            long currentEpochDay = LocalDate.now().toEpochDay();
            if (mLearnedHintLastShownEpochDay < currentEpochDay) {
                if (mContext != null) {
                    Settings.Secure.putLong(
                            mContext.getContentResolver(),
                            LEARNED_HINT_LAST_SHOWN_KEY,
                            currentEpochDay);
                }
                mLearnedHintLastShownEpochDay = currentEpochDay;
                mAssistHandleCallbacks.showAndGo();
            }
        }
    }

    private void callbackForUnlearnedState() {
        if (mAssistHandleCallbacks == null) {
            return;
        }

        if (!isFullyAwake() || mIsNavBarHidden || isSuppressed()) {
            mAssistHandleCallbacks.hide();
        } else if (mOnLockscreen) {
            mAssistHandleCallbacks.showAndStay();
        } else if (mIsLauncherShowing) {
            mAssistHandleCallbacks.showAndGo();
        } else if (mConsecutiveTaskSwitches == 1) {
            mAssistHandleCallbacks.showAndGoDelayed(
                    getShowAndGoDelayedShortDelayMs(), /* hideIfShowing = */ false);
        } else {
            mAssistHandleCallbacks.showAndGoDelayed(
                    getShowAndGoDelayedLongDelayMs(), /* hideIfShowing = */ true);
        }
    }

    private boolean isSuppressed() {
        if (mOnLockscreen) {
            return getSuppressOnLockscreen();
        } else if (mIsLauncherShowing) {
            return getSuppressOnLauncher();
        } else {
            return getSuppressOnApps();
        }
    }

    private void updateLearningStatus() {
        if (mContext == null) {
            return;
        }

        long currentTimestamp = mClock.currentTimeMillis();
        mLearningTimeElapsed += currentTimestamp - mLastLearningTimestamp;
        mLastLearningTimestamp = currentTimestamp;

        mIsLearned =
                mLearningCount >= getLearningCount() || mLearningTimeElapsed >= getLearningTimeMs();

        mHandler.post(() -> Settings.Secure.putLong(
                mContext.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, mLearningTimeElapsed));
    }

    private void resetConsecutiveTaskSwitches() {
        mHandler.removeCallbacks(mResetConsecutiveTaskSwitches);
        mConsecutiveTaskSwitches = 0;
    }

    private void rescheduleConsecutiveTaskSwitchesReset() {
        mHandler.removeCallbacks(mResetConsecutiveTaskSwitches);
        mHandler.postDelayed(mResetConsecutiveTaskSwitches, getShowAndGoDelayResetTimeoutMs());
    }

    private boolean isFullyAwake() {
        return mIsAwake && !mIsDozing;
    }

    private long getLearningTimeMs() {
        return mPhenotypeHelper.getLong(
                SystemUiDeviceConfigFlags.ASSIST_HANDLES_LEARN_TIME_MS,
                DEFAULT_LEARNING_TIME_MS);
    }

    private int getLearningCount() {
        return mPhenotypeHelper.getInt(
                SystemUiDeviceConfigFlags.ASSIST_HANDLES_LEARN_COUNT,
                DEFAULT_LEARNING_COUNT);
    }

    private long getShowAndGoDelayedShortDelayMs() {
        return mPhenotypeHelper.getLong(
                SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DELAYED_SHORT_DELAY_MS,
                DEFAULT_SHOW_AND_GO_DELAYED_SHORT_DELAY_MS);
    }

    private long getShowAndGoDelayedLongDelayMs() {
        return mPhenotypeHelper.getLong(
                SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DELAYED_LONG_DELAY_MS,
                DEFAULT_SHOW_AND_GO_DELAYED_LONG_DELAY_MS);
    }

    private long getShowAndGoDelayResetTimeoutMs() {
        return mPhenotypeHelper.getLong(
                SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DELAY_RESET_TIMEOUT_MS,
                DEFAULT_SHOW_AND_GO_DELAY_RESET_TIMEOUT_MS);
    }

    private boolean getSuppressOnLockscreen() {
        return mPhenotypeHelper.getBoolean(
                SystemUiDeviceConfigFlags.ASSIST_HANDLES_SUPPRESS_ON_LOCKSCREEN,
                DEFAULT_SUPPRESS_ON_LOCKSCREEN);
    }

    private boolean getSuppressOnLauncher() {
        return mPhenotypeHelper.getBoolean(
                SystemUiDeviceConfigFlags.ASSIST_HANDLES_SUPPRESS_ON_LAUNCHER,
                DEFAULT_SUPPRESS_ON_LAUNCHER);
    }

    private boolean getSuppressOnApps() {
        return mPhenotypeHelper.getBoolean(
                SystemUiDeviceConfigFlags.ASSIST_HANDLES_SUPPRESS_ON_APPS,
                DEFAULT_SUPPRESS_ON_APPS);
    }

    private boolean getShowWhenTaught() {
        return mPhenotypeHelper.getBoolean(
                SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_WHEN_TAUGHT,
                DEFAULT_SHOW_WHEN_TAUGHT);
    }

    @Override
    public void dump(PrintWriter pw, String prefix) {
        pw.println(prefix + "Current AssistHandleReminderExpBehavior State:");
        pw.println(prefix + "   mOnLockscreen=" + mOnLockscreen);
        pw.println(prefix + "   mIsDozing=" + mIsDozing);
        pw.println(prefix + "   mIsAwake=" + mIsAwake);
        pw.println(prefix + "   mRunningTaskId=" + mRunningTaskId);
        pw.println(prefix + "   mDefaultHome=" + mDefaultHome);
        pw.println(prefix + "   mIsNavBarHidden=" + mIsNavBarHidden);
        pw.println(prefix + "   mIsLauncherShowing=" + mIsLauncherShowing);
        pw.println(prefix + "   mConsecutiveTaskSwitches=" + mConsecutiveTaskSwitches);
        pw.println(prefix + "   mIsLearned=" + mIsLearned);
        pw.println(prefix + "   mLastLearningTimestamp=" + mLastLearningTimestamp);
        pw.println(prefix + "   mLearningTimeElapsed=" + mLearningTimeElapsed);
        pw.println(prefix + "   mLearningCount=" + mLearningCount);
        pw.println(prefix + "   mLearnedHintLastShownEpochDay=" + mLearnedHintLastShownEpochDay);
        pw.println(
                prefix + "   mAssistHandleCallbacks present: " + (mAssistHandleCallbacks != null));

        pw.println(prefix + "   Phenotype Flags:");
        pw.println(prefix + "      "
                + SystemUiDeviceConfigFlags.ASSIST_HANDLES_LEARN_TIME_MS
                + "="
                + getLearningTimeMs());
        pw.println(prefix + "      "
                + SystemUiDeviceConfigFlags.ASSIST_HANDLES_LEARN_COUNT
                + "="
                + getLearningCount());
        pw.println(prefix + "      "
                + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DELAYED_SHORT_DELAY_MS
                + "="
                + getShowAndGoDelayedShortDelayMs());
        pw.println(prefix + "      "
                + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DELAYED_LONG_DELAY_MS
                + "="
                + getShowAndGoDelayedLongDelayMs());
        pw.println(prefix + "      "
                + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DELAY_RESET_TIMEOUT_MS
                + "="
                + getShowAndGoDelayResetTimeoutMs());
        pw.println(prefix + "      "
                + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SUPPRESS_ON_LOCKSCREEN
                + "="
                + getSuppressOnLockscreen());
        pw.println(prefix + "      "
                + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SUPPRESS_ON_LAUNCHER
                + "="
                + getSuppressOnLauncher());
        pw.println(prefix + "      "
                + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SUPPRESS_ON_APPS
                + "="
                + getSuppressOnApps());
        pw.println(prefix + "      "
                + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_WHEN_TAUGHT
                + "="
                + getShowWhenTaught());
    }
}
