/*
 * 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 android.content.ComponentName;
import android.content.Context;
import android.os.Handler;
import android.os.SystemClock;
import android.util.Log;

import androidx.annotation.Nullable;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.AssistUtils;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.Dependency;
import com.android.systemui.DumpController;
import com.android.systemui.Dumpable;
import com.android.systemui.ScreenDecorations;
import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.phone.NavigationModeController;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.EnumMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

/**
 * A class for managing Assistant handle logic.
 *
 * Controls when visual handles for Assistant gesture affordance should be shown or hidden using an
 * {@link AssistHandleBehavior}.
 */
public final class AssistHandleBehaviorController implements AssistHandleCallbacks, Dumpable {

    private static final String TAG = "AssistHandleBehavior";

    private static final long DEFAULT_SHOWN_FREQUENCY_THRESHOLD_MS = 0;
    private static final long DEFAULT_SHOW_AND_GO_DURATION_MS = TimeUnit.SECONDS.toMillis(3);

    /**
     * This is the default behavior that will be used once the system is up. It will be set once the
     * behavior dependencies are available. This ensures proper behavior lifecycle.
     */
    private static final AssistHandleBehavior DEFAULT_BEHAVIOR = AssistHandleBehavior.REMINDER_EXP;

    private final Context mContext;
    private final AssistUtils mAssistUtils;
    private final Handler mHandler;
    private final Runnable mHideHandles = this::hideHandles;
    private final Runnable mShowAndGo = this::showAndGoInternal;
    private final Supplier<ScreenDecorations> mScreenDecorationsSupplier;
    private final PhenotypeHelper mPhenotypeHelper;
    private final Map<AssistHandleBehavior, BehaviorController> mBehaviorMap =
            new EnumMap<>(AssistHandleBehavior.class);

    private boolean mHandlesShowing = false;
    private long mHandlesLastHiddenAt;
    private long mShowAndGoEndsAt;
    /**
     * This should always be initialized as {@link AssistHandleBehavior#OFF} to ensure proper
     * behavior lifecycle.
     */
    private AssistHandleBehavior mCurrentBehavior = AssistHandleBehavior.OFF;
    private boolean mInGesturalMode;

    AssistHandleBehaviorController(Context context, AssistUtils assistUtils, Handler handler) {
        this(
                context,
                assistUtils,
                handler,
                () -> SysUiServiceProvider.getComponent(context, ScreenDecorations.class),
                new PhenotypeHelper(),
                /* testBehavior = */ null);
    }

    @VisibleForTesting
    AssistHandleBehaviorController(
            Context context,
            AssistUtils assistUtils,
            Handler handler,
            Supplier<ScreenDecorations> screenDecorationsSupplier,
            PhenotypeHelper phenotypeHelper,
            @Nullable BehaviorController testBehavior) {
        mContext = context;
        mAssistUtils = assistUtils;
        mHandler = handler;
        mScreenDecorationsSupplier = screenDecorationsSupplier;
        mPhenotypeHelper = phenotypeHelper;
        mBehaviorMap.put(AssistHandleBehavior.OFF, new AssistHandleOffBehavior());
        mBehaviorMap.put(AssistHandleBehavior.LIKE_HOME, new AssistHandleLikeHomeBehavior());
        mBehaviorMap.put(
                AssistHandleBehavior.REMINDER_EXP,
                new AssistHandleReminderExpBehavior(handler, phenotypeHelper));
        if (testBehavior != null) {
            mBehaviorMap.put(AssistHandleBehavior.TEST, testBehavior);
        }

        mInGesturalMode = QuickStepContract.isGesturalMode(
                Dependency.get(NavigationModeController.class)
                        .addListener(this::handleNavigationModeChange));

        setBehavior(getBehaviorMode());
        mPhenotypeHelper.addOnPropertiesChangedListener(
                mHandler::post,
                (properties) -> {
                    if (properties.getKeyset().contains(
                            SystemUiDeviceConfigFlags.ASSIST_HANDLES_BEHAVIOR_MODE)) {
                        setBehavior(properties.getString(
                                SystemUiDeviceConfigFlags.ASSIST_HANDLES_BEHAVIOR_MODE, null));
                    }
                });
        Dependency.get(DumpController.class).addListener(this);
    }

    @Override // AssistHandleCallbacks
    public void hide() {
        clearPendingCommands();
        mHandler.post(mHideHandles);
    }

    @Override // AssistHandleCallbacks
    public void showAndGo() {
        clearPendingCommands();
        mHandler.post(mShowAndGo);
    }

    private void showAndGoInternal() {
        maybeShowHandles(/* ignoreThreshold = */ false);
        long showAndGoDuration = getShowAndGoDuration();
        mShowAndGoEndsAt = SystemClock.elapsedRealtime() + showAndGoDuration;
        mHandler.postDelayed(mHideHandles, showAndGoDuration);
    }

    @Override // AssistHandleCallbacks
    public void showAndGoDelayed(long delayMs, boolean hideIfShowing) {
        clearPendingCommands();
        if (hideIfShowing) {
            mHandler.post(mHideHandles);
        }
        mHandler.postDelayed(mShowAndGo, delayMs);
    }

    @Override // AssistHandleCallbacks
    public void showAndStay() {
        clearPendingCommands();
        mHandler.post(() -> maybeShowHandles(/* ignoreThreshold = */ true));
    }

    public long getShowAndGoRemainingTimeMs() {
        return Long.max(mShowAndGoEndsAt - SystemClock.elapsedRealtime(), 0);
    }

    boolean areHandlesShowing() {
        return mHandlesShowing;
    }

    void onAssistantGesturePerformed() {
        mBehaviorMap.get(mCurrentBehavior).onAssistantGesturePerformed();
    }

    void setBehavior(AssistHandleBehavior behavior) {
        if (mCurrentBehavior == behavior) {
            return;
        }

        if (!mBehaviorMap.containsKey(behavior)) {
            Log.e(TAG, "Unsupported behavior requested: " + behavior.toString());
            return;
        }

        if (mInGesturalMode) {
            mBehaviorMap.get(mCurrentBehavior).onModeDeactivated();
            mBehaviorMap.get(behavior).onModeActivated(mContext, /* callbacks = */ this);
        }

        mCurrentBehavior = behavior;
    }

    private void setBehavior(@Nullable String behavior) {
        try {
            setBehavior(AssistHandleBehavior.valueOf(behavior));
        } catch (IllegalArgumentException | NullPointerException e) {
            Log.e(TAG, "Invalid behavior: " + behavior, e);
        }
    }

    private boolean handlesUnblocked(boolean ignoreThreshold) {
        long timeSinceHidden = SystemClock.elapsedRealtime() - mHandlesLastHiddenAt;
        boolean notThrottled = ignoreThreshold || timeSinceHidden >= getShownFrequencyThreshold();
        ComponentName assistantComponent =
                mAssistUtils.getAssistComponentForUser(KeyguardUpdateMonitor.getCurrentUser());
        return notThrottled && assistantComponent != null;
    }

    private long getShownFrequencyThreshold() {
        return mPhenotypeHelper.getLong(
                SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOWN_FREQUENCY_THRESHOLD_MS,
                DEFAULT_SHOWN_FREQUENCY_THRESHOLD_MS);
    }

    private long getShowAndGoDuration() {
        return mPhenotypeHelper.getLong(
                SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DURATION_MS,
                DEFAULT_SHOW_AND_GO_DURATION_MS);
    }

    private String getBehaviorMode() {
        return mPhenotypeHelper.getString(
                SystemUiDeviceConfigFlags.ASSIST_HANDLES_BEHAVIOR_MODE,
                DEFAULT_BEHAVIOR.toString());
    }

    private void maybeShowHandles(boolean ignoreThreshold) {
        if (mHandlesShowing) {
            return;
        }

        if (handlesUnblocked(ignoreThreshold)) {
            ScreenDecorations screenDecorations = mScreenDecorationsSupplier.get();
            if (screenDecorations == null) {
                Log.w(TAG, "Couldn't show handles, ScreenDecorations unavailable");
            } else {
                mHandlesShowing = true;
                screenDecorations.setAssistHintVisible(true);
            }
        }
    }

    private void hideHandles() {
        if (!mHandlesShowing) {
            return;
        }

        ScreenDecorations screenDecorations = mScreenDecorationsSupplier.get();
        if (screenDecorations == null) {
            Log.w(TAG, "Couldn't hide handles, ScreenDecorations unavailable");
        } else {
            mHandlesShowing = false;
            mHandlesLastHiddenAt = SystemClock.elapsedRealtime();
            screenDecorations.setAssistHintVisible(false);
        }
    }

    private void handleNavigationModeChange(int navigationMode) {
        boolean inGesturalMode = QuickStepContract.isGesturalMode(navigationMode);
        if (mInGesturalMode == inGesturalMode) {
            return;
        }

        mInGesturalMode = inGesturalMode;
        if (mInGesturalMode) {
            mBehaviorMap.get(mCurrentBehavior).onModeActivated(mContext, /* callbacks = */ this);
        } else {
            mBehaviorMap.get(mCurrentBehavior).onModeDeactivated();
            hide();
        }
    }

    private void clearPendingCommands() {
        mHandler.removeCallbacks(mHideHandles);
        mHandler.removeCallbacks(mShowAndGo);
        mShowAndGoEndsAt = 0;
    }

    @VisibleForTesting
    void setInGesturalModeForTest(boolean inGesturalMode) {
        mInGesturalMode = inGesturalMode;
    }

    @Override // Dumpable
    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        pw.println("Current AssistHandleBehaviorController State:");

        pw.println("   mHandlesShowing=" + mHandlesShowing);
        pw.println("   mHandlesLastHiddenAt=" + mHandlesLastHiddenAt);
        pw.println("   mInGesturalMode=" + mInGesturalMode);

        pw.println("   Phenotype Flags:");
        pw.println("      "
                + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DURATION_MS
                + "="
                + getShowAndGoDuration());
        pw.println("      "
                + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOWN_FREQUENCY_THRESHOLD_MS
                + "="
                + getShownFrequencyThreshold());
        pw.println("      "
                + SystemUiDeviceConfigFlags.ASSIST_HANDLES_BEHAVIOR_MODE
                + "="
                + getBehaviorMode());

        pw.println("   mCurrentBehavior=" + mCurrentBehavior.toString());
        mBehaviorMap.get(mCurrentBehavior).dump(pw, "   ");
    }

    interface BehaviorController {
        void onModeActivated(Context context, AssistHandleCallbacks callbacks);
        default void onModeDeactivated() {}
        default void onAssistantGesturePerformed() {}
        default void dump(PrintWriter pw, String prefix) {}
    }
}
