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

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.AdditionalAnswers.answerVoid;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.admin.IKeyguardCallback;
import android.app.admin.IKeyguardClient;
import android.content.ComponentName;
import android.content.Intent;
import android.os.Handler;
import android.os.RemoteException;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
import android.testing.ViewUtils;
import android.view.SurfaceControlViewHost;
import android.view.SurfaceView;

import androidx.test.filters.SmallTest;

import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.systemui.SysuiTestCase;

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

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

    private static final int TARGET_USER_ID = KeyguardUpdateMonitor.getCurrentUser();

    private AdminSecondaryLockScreenController mTestController;
    private ComponentName mComponentName;
    private Intent mServiceIntent;
    private TestableLooper mTestableLooper;
    private KeyguardSecurityContainer mKeyguardSecurityContainer;

    @Mock
    private Handler mHandler;
    @Mock
    private IKeyguardClient.Stub mKeyguardClient;
    @Mock
    private KeyguardSecurityCallback mKeyguardCallback;
    @Mock
    private KeyguardUpdateMonitor mUpdateMonitor;
    @Mock
    private SurfaceControlViewHost.SurfacePackage mSurfacePackage;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);

        mKeyguardSecurityContainer = spy(new KeyguardSecurityContainer(mContext));
        ViewUtils.attachView(mKeyguardSecurityContainer);

        mTestableLooper = TestableLooper.get(this);
        mComponentName = new ComponentName(mContext, "FakeKeyguardClient.class");
        mServiceIntent = new Intent().setComponent(mComponentName);

        mContext.addMockService(mComponentName, mKeyguardClient);
        // Have Stub.asInterface return the mocked interface.
        when(mKeyguardClient.queryLocalInterface(anyString())).thenReturn(mKeyguardClient);
        when(mKeyguardClient.asBinder()).thenReturn(mKeyguardClient);

        mTestController = new AdminSecondaryLockScreenController.Factory(
                mContext, mKeyguardSecurityContainer, mUpdateMonitor, mHandler)
                .create(mKeyguardCallback);
    }

    @After
    public void tearDown() {
        ViewUtils.detachView(mKeyguardSecurityContainer);
    }

    @Test
    public void testShow() throws Exception {
        doAnswer(invocation -> {
            IKeyguardCallback callback = (IKeyguardCallback) invocation.getArguments()[1];
            callback.onRemoteContentReady(mSurfacePackage);
            return null;
        }).when(mKeyguardClient).onCreateKeyguardSurface(any(), any(IKeyguardCallback.class));

        mTestController.show(mServiceIntent);

        verifySurfaceReady();
        assertThat(mContext.isBound(mComponentName)).isTrue();
    }

    @Test
    public void testShow_dismissedByCallback() throws Exception {
        doAnswer(answerVoid(Runnable::run)).when(mHandler).post(any(Runnable.class));
        doAnswer(invocation -> {
            IKeyguardCallback callback = (IKeyguardCallback) invocation.getArguments()[1];
            callback.onDismiss();
            return null;
        }).when(mKeyguardClient).onCreateKeyguardSurface(any(), any(IKeyguardCallback.class));

        mTestController.show(mServiceIntent);

        verifyViewDismissed(verifySurfaceReady());
    }

    @Test
    public void testHide() throws Exception {
        // Show the view first, then hide.
        doAnswer(invocation -> {
            IKeyguardCallback callback = (IKeyguardCallback) invocation.getArguments()[1];
            callback.onRemoteContentReady(mSurfacePackage);
            return null;
        }).when(mKeyguardClient).onCreateKeyguardSurface(any(), any(IKeyguardCallback.class));

        mTestController.show(mServiceIntent);
        SurfaceView v = verifySurfaceReady();

        mTestController.hide();
        verify(mKeyguardSecurityContainer).removeView(v);
        assertThat(mContext.isBound(mComponentName)).isFalse();
    }

    @Test
    public void testHide_notShown() throws Exception {
        mTestController.hide();
        // Nothing should happen if trying to hide when the view isn't attached yet.
        verify(mKeyguardSecurityContainer, never()).removeView(any(SurfaceView.class));
    }

    @Test
    public void testDismissed_onCreateKeyguardSurface_RemoteException() throws Exception {
        doThrow(new RemoteException()).when(mKeyguardClient)
                .onCreateKeyguardSurface(any(), any(IKeyguardCallback.class));

        mTestController.show(mServiceIntent);

        verifyViewDismissed(verifySurfaceReady());
    }

    @Test
    public void testDismissed_onCreateKeyguardSurface_timeout() throws Exception {
        // Mocked KeyguardClient never handles the onCreateKeyguardSurface, so the operation
        // times out, resulting in the view being dismissed.
        doAnswer(answerVoid(Runnable::run)).when(mHandler)
                .postDelayed(any(Runnable.class), anyLong());

        mTestController.show(mServiceIntent);

        verifyViewDismissed(verifySurfaceReady());
    }

    private SurfaceView verifySurfaceReady() throws Exception {
        mTestableLooper.processAllMessages();
        ArgumentCaptor<SurfaceView> captor = ArgumentCaptor.forClass(SurfaceView.class);
        verify(mKeyguardSecurityContainer).addView(captor.capture());

        mTestableLooper.processAllMessages();
        verify(mKeyguardClient).onCreateKeyguardSurface(any(), any(IKeyguardCallback.class));
        return captor.getValue();
    }

    private void verifyViewDismissed(SurfaceView v) throws Exception {
        verify(mKeyguardSecurityContainer).removeView(v);
        verify(mKeyguardCallback).dismiss(true, TARGET_USER_ID, true, SecurityMode.Invalid);
        assertThat(mContext.isBound(mComponentName)).isFalse();
    }
}
