/*
 * 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 org.mockito.AdditionalAnswers.answerVoid;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;

import android.content.ComponentName;
import android.os.Handler;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;

import androidx.test.filters.SmallTest;

import com.android.internal.app.AssistUtils;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.systemui.DumpController;
import com.android.systemui.ScreenDecorations;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.statusbar.phone.NavigationModeController;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.util.EnumMap;
import java.util.Map;

@SmallTest
@RunWith(AndroidTestingRunner.class)
@RunWithLooper
public class AssistHandleBehaviorControllerTest extends SysuiTestCase {

    private static final ComponentName COMPONENT_NAME = new ComponentName("", "");

    private AssistHandleBehaviorController mAssistHandleBehaviorController;

    @Mock private ScreenDecorations mMockScreenDecorations;
    @Mock private AssistUtils mMockAssistUtils;
    @Mock private Handler mMockHandler;
    @Mock private PhenotypeHelper mMockPhenotypeHelper;
    @Mock private AssistHandleOffBehavior mMockOffBehavior;
    @Mock private AssistHandleLikeHomeBehavior mMockLikeHomeBehavior;
    @Mock private AssistHandleReminderExpBehavior mMockReminderExpBehavior;
    @Mock private AssistHandleBehaviorController.BehaviorController mMockTestBehavior;
    @Mock private NavigationModeController mMockNavigationModeController;
    @Mock private DumpController mMockDumpController;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        mDependency.injectMockDependency(StatusBarStateController.class);
        mDependency.injectMockDependency(OverviewProxyService.class);
        doAnswer(answerVoid(Runnable::run)).when(mMockHandler).post(any(Runnable.class));
        doAnswer(answerVoid(Runnable::run)).when(mMockHandler)
                .postDelayed(any(Runnable.class), anyLong());

        Map<AssistHandleBehavior, AssistHandleBehaviorController.BehaviorController> behaviorMap =
                new EnumMap<>(AssistHandleBehavior.class);
        behaviorMap.put(AssistHandleBehavior.OFF, mMockOffBehavior);
        behaviorMap.put(AssistHandleBehavior.LIKE_HOME, mMockLikeHomeBehavior);
        behaviorMap.put(AssistHandleBehavior.REMINDER_EXP, mMockReminderExpBehavior);
        behaviorMap.put(AssistHandleBehavior.TEST, mMockTestBehavior);

        mAssistHandleBehaviorController =
                new AssistHandleBehaviorController(
                        mContext,
                        mMockAssistUtils,
                        mMockHandler,
                        () -> mMockScreenDecorations,
                        mMockPhenotypeHelper,
                        behaviorMap,
                        mMockNavigationModeController,
                        mMockDumpController);
    }

    @After
    public void teardown() {
        mAssistHandleBehaviorController.setBehavior(AssistHandleBehavior.OFF);
    }

    @Test
    public void hide_hidesHandlesWhenShowing() {
        // Arrange
        when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
        mAssistHandleBehaviorController.showAndStay();
        reset(mMockScreenDecorations);

        // Act
        mAssistHandleBehaviorController.hide();

        // Assert
        verify(mMockScreenDecorations).setAssistHintVisible(false);
        verifyNoMoreInteractions(mMockScreenDecorations);
    }

    @Test
    public void hide_doesNothingWhenHiding() {
        // Arrange
        when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
        mAssistHandleBehaviorController.hide();
        reset(mMockScreenDecorations);

        // Act
        mAssistHandleBehaviorController.hide();

        // Assert
        verifyNoMoreInteractions(mMockScreenDecorations);
    }

    @Test
    public void showAndStay_showsHandlesWhenHiding() {
        // Arrange
        when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
        mAssistHandleBehaviorController.hide();
        reset(mMockScreenDecorations);

        // Act
        mAssistHandleBehaviorController.showAndStay();

        // Assert
        verify(mMockScreenDecorations).setAssistHintVisible(true);
        verifyNoMoreInteractions(mMockScreenDecorations);
    }

    @Test
    public void showAndStay_doesNothingWhenShowing() {
        // Arrange
        when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
        mAssistHandleBehaviorController.showAndStay();
        reset(mMockScreenDecorations);

        // Act
        mAssistHandleBehaviorController.showAndStay();

        // Assert
        verifyNoMoreInteractions(mMockScreenDecorations);
    }

    @Test
    public void showAndStay_doesNothingWhenThereIsNoAssistant() {
        // Arrange
        when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(null);
        mAssistHandleBehaviorController.hide();
        reset(mMockScreenDecorations);

        // Act
        mAssistHandleBehaviorController.showAndStay();

        // Assert
        verifyNoMoreInteractions(mMockScreenDecorations);
    }

    @Test
    public void showAndGo_showsThenHidesHandlesWhenHiding() {
        // Arrange
        when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
        mAssistHandleBehaviorController.hide();
        reset(mMockScreenDecorations);

        // Act
        mAssistHandleBehaviorController.showAndGo();

        // Assert
        InOrder inOrder = inOrder(mMockScreenDecorations);
        inOrder.verify(mMockScreenDecorations).setAssistHintVisible(true);
        inOrder.verify(mMockScreenDecorations).setAssistHintVisible(false);
        inOrder.verifyNoMoreInteractions();
    }

    @Test
    public void showAndGo_hidesHandlesAfterTimeoutWhenShowing() {
        // Arrange
        when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
        mAssistHandleBehaviorController.showAndStay();
        reset(mMockScreenDecorations);

        // Act
        mAssistHandleBehaviorController.showAndGo();

        // Assert
        verify(mMockScreenDecorations).setAssistHintVisible(false);
        verifyNoMoreInteractions(mMockScreenDecorations);
    }

    @Test
    public void showAndGo_doesNothingIfRecentlyHidden() {
        // Arrange
        when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
        when(mMockPhenotypeHelper.getLong(
                eq(SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOWN_FREQUENCY_THRESHOLD_MS),
                anyLong())).thenReturn(10000L);
        mAssistHandleBehaviorController.showAndGo();
        reset(mMockScreenDecorations);

        // Act
        mAssistHandleBehaviorController.showAndGo();

        // Assert
        verifyNoMoreInteractions(mMockScreenDecorations);
    }

    @Test
    public void showAndGo_doesNothingWhenThereIsNoAssistant() {
        // Arrange
        when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(null);
        mAssistHandleBehaviorController.hide();
        reset(mMockScreenDecorations);

        // Act
        mAssistHandleBehaviorController.showAndGo();

        // Assert
        verifyNoMoreInteractions(mMockScreenDecorations);
    }

    @Test
    public void showAndGoDelayed_showsThenHidesHandlesWhenHiding() {
        // Arrange
        when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
        mAssistHandleBehaviorController.hide();
        reset(mMockScreenDecorations);

        // Act
        mAssistHandleBehaviorController.showAndGoDelayed(1000, false);

        // Assert
        InOrder inOrder = inOrder(mMockScreenDecorations);
        inOrder.verify(mMockScreenDecorations).setAssistHintVisible(true);
        inOrder.verify(mMockScreenDecorations).setAssistHintVisible(false);
        inOrder.verifyNoMoreInteractions();
    }

    @Test
    public void showAndGoDelayed_hidesHandlesAfterTimeoutWhenShowing() {
        // Arrange
        when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
        mAssistHandleBehaviorController.showAndStay();
        reset(mMockScreenDecorations);

        // Act
        mAssistHandleBehaviorController.showAndGoDelayed(1000, false);

        // Assert
        verify(mMockScreenDecorations).setAssistHintVisible(false);
        verifyNoMoreInteractions(mMockScreenDecorations);
    }

    @Test
    public void showAndGoDelayed_hidesInitiallyThenShowsThenHidesAfterTimeoutWhenHideRequested() {
        // Arrange
        when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
        mAssistHandleBehaviorController.showAndStay();
        reset(mMockScreenDecorations);

        // Act
        mAssistHandleBehaviorController.showAndGoDelayed(1000, true);

        // Assert
        InOrder inOrder = inOrder(mMockScreenDecorations);
        inOrder.verify(mMockScreenDecorations).setAssistHintVisible(false);
        inOrder.verify(mMockScreenDecorations).setAssistHintVisible(true);
        inOrder.verify(mMockScreenDecorations).setAssistHintVisible(false);
        inOrder.verifyNoMoreInteractions();
    }

    @Test
    public void showAndGoDelayed_doesNothingIfRecentlyHidden() {
        // Arrange
        when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
        when(mMockPhenotypeHelper.getLong(
                eq(SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOWN_FREQUENCY_THRESHOLD_MS),
                anyLong())).thenReturn(10000L);
        mAssistHandleBehaviorController.showAndGo();
        reset(mMockScreenDecorations);

        // Act
        mAssistHandleBehaviorController.showAndGoDelayed(1000, false);

        // Assert
        verifyNoMoreInteractions(mMockScreenDecorations);
    }

    @Test
    public void showAndGoDelayed_doesNothingWhenThereIsNoAssistant() {
        // Arrange
        when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(null);
        mAssistHandleBehaviorController.hide();
        reset(mMockScreenDecorations);

        // Act
        mAssistHandleBehaviorController.showAndGoDelayed(1000, false);

        // Assert
        verifyNoMoreInteractions(mMockScreenDecorations);
    }

    @Test
    public void setBehavior_activatesTheBehaviorWhenInGesturalMode() {
        // Arrange
        when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
        mAssistHandleBehaviorController.setInGesturalModeForTest(true);

        // Act
        mAssistHandleBehaviorController.setBehavior(AssistHandleBehavior.TEST);

        // Assert
        verify(mMockTestBehavior).onModeActivated(mContext, mAssistHandleBehaviorController);
        verifyNoMoreInteractions(mMockTestBehavior);
    }

    @Test
    public void setBehavior_deactivatesThePreviousBehaviorWhenInGesturalMode() {
        // Arrange
        when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
        mAssistHandleBehaviorController.setBehavior(AssistHandleBehavior.TEST);
        mAssistHandleBehaviorController.setInGesturalModeForTest(true);
        reset(mMockTestBehavior);

        // Act
        mAssistHandleBehaviorController.setBehavior(AssistHandleBehavior.OFF);

        // Assert
        verify(mMockTestBehavior).onModeDeactivated();
        verifyNoMoreInteractions(mMockTestBehavior);
    }

    @Test
    public void setBehavior_doesNothingWhenNotInGesturalMode() {
        // Arrange
        when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
        mAssistHandleBehaviorController.setInGesturalModeForTest(false);

        // Act
        mAssistHandleBehaviorController.setBehavior(AssistHandleBehavior.TEST);

        // Assert
        verifyNoMoreInteractions(mMockTestBehavior);
    }
}
