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

import static com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider.ScreenshotSmartActionType.REGULAR_SMART_ACTIONS;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.Notification;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
import android.testing.AndroidTestingRunner;

import androidx.test.filters.SmallTest;

import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.screenshot.ScreenshotController.SavedImageData.ActionTransition;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

@SmallTest
@RunWith(AndroidTestingRunner.class)
/**
 * Tests for exception handling and  bitmap configuration in adding smart actions to Screenshot
 * Notification.
 */
public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase {
    private ScreenshotNotificationSmartActionsProvider mSmartActionsProvider;
    private ScreenshotSmartActions mScreenshotSmartActions;
    private Handler mHandler;

    @Before
    public void setup() {
        mSmartActionsProvider = mock(
                ScreenshotNotificationSmartActionsProvider.class);
        mScreenshotSmartActions = new ScreenshotSmartActions();
        mHandler = mock(Handler.class);
    }

    // Tests any exception thrown in getting smart actions future does not affect regular
    // screenshot flow.
    @Test
    public void testExceptionHandlingInGetSmartActionsFuture()
            throws Exception {
        Bitmap bitmap = mock(Bitmap.class);
        when(bitmap.getConfig()).thenReturn(Bitmap.Config.HARDWARE);
        ScreenshotNotificationSmartActionsProvider smartActionsProvider = mock(
                ScreenshotNotificationSmartActionsProvider.class);
        when(smartActionsProvider.getActions(any(), any(), any(), any(), any(), any()))
            .thenThrow(RuntimeException.class);
        CompletableFuture<List<Notification.Action>> smartActionsFuture =
                mScreenshotSmartActions.getSmartActionsFuture(
                        "", Uri.parse("content://authority/data"), bitmap, smartActionsProvider,
                        REGULAR_SMART_ACTIONS,
                        true, UserHandle.of(UserHandle.myUserId()));
        assertNotNull(smartActionsFuture);
        List<Notification.Action> smartActions = smartActionsFuture.get(5, TimeUnit.MILLISECONDS);
        assertEquals(Collections.emptyList(), smartActions);
    }

    // Tests any exception thrown in waiting for smart actions future to complete does
    // not affect regular screenshot flow.
    @Test
    public void testExceptionHandlingInGetSmartActions()
            throws Exception {
        CompletableFuture<List<Notification.Action>> smartActionsFuture = mock(
                CompletableFuture.class);
        int timeoutMs = 1000;
        when(smartActionsFuture.get(timeoutMs, TimeUnit.MILLISECONDS)).thenThrow(
                RuntimeException.class);
        List<Notification.Action> actions = mScreenshotSmartActions.getSmartActions(
                "", smartActionsFuture, timeoutMs, mSmartActionsProvider, REGULAR_SMART_ACTIONS);
        assertEquals(Collections.emptyList(), actions);
    }

    // Tests any exception thrown in notifying feedback does not affect regular screenshot flow.
    @Test
    public void testExceptionHandlingInNotifyingFeedback()
            throws Exception {
        doThrow(RuntimeException.class).when(mSmartActionsProvider).notifyOp(any(), any(), any(),
                anyLong());
        mScreenshotSmartActions.notifyScreenshotOp(null, mSmartActionsProvider, null, null, -1);
    }

    // Tests for a non-hardware bitmap, ScreenshotNotificationSmartActionsProvider is never invoked
    // and a completed future is returned.
    @Test
    public void testUnsupportedBitmapConfiguration()
            throws Exception {
        Bitmap bitmap = mock(Bitmap.class);
        when(bitmap.getConfig()).thenReturn(Bitmap.Config.RGB_565);
        CompletableFuture<List<Notification.Action>> smartActionsFuture =
                mScreenshotSmartActions.getSmartActionsFuture(
                        "", Uri.parse("content://autority/data"), bitmap, mSmartActionsProvider,
                        REGULAR_SMART_ACTIONS,
                        true, UserHandle.of(UserHandle.myUserId()));
        verify(mSmartActionsProvider, never()).getActions(any(), any(), any(), any(), any(), any());
        assertNotNull(smartActionsFuture);
        List<Notification.Action> smartActions = smartActionsFuture.get(5, TimeUnit.MILLISECONDS);
        assertEquals(Collections.emptyList(), smartActions);
    }

    // Tests for a hardware bitmap, ScreenshotNotificationSmartActionsProvider is invoked once.
    @Test
    public void testScreenshotNotificationSmartActionsProviderInvokedOnce() {
        Bitmap bitmap = mock(Bitmap.class);
        when(bitmap.getConfig()).thenReturn(Bitmap.Config.HARDWARE);
        mScreenshotSmartActions.getSmartActionsFuture(
                "", Uri.parse("content://autority/data"), bitmap, mSmartActionsProvider,
                REGULAR_SMART_ACTIONS, true,
                UserHandle.of(UserHandle.myUserId()));
        verify(mSmartActionsProvider, times(1)).getActions(
                any(), any(), any(), any(), any(), any());
    }

    // Tests for a hardware bitmap, a completed future is returned.
    @Test
    public void testSupportedBitmapConfiguration()
            throws Exception {
        Bitmap bitmap = mock(Bitmap.class);
        when(bitmap.getConfig()).thenReturn(Bitmap.Config.HARDWARE);
        ScreenshotNotificationSmartActionsProvider actionsProvider =
                SystemUIFactory.getInstance().createScreenshotNotificationSmartActionsProvider(
                        mContext, null, mHandler);
        CompletableFuture<List<Notification.Action>> smartActionsFuture =
                mScreenshotSmartActions.getSmartActionsFuture("", null, bitmap,
                        actionsProvider, REGULAR_SMART_ACTIONS,
                        true, UserHandle.of(UserHandle.myUserId()));
        assertNotNull(smartActionsFuture);
        List<Notification.Action> smartActions = smartActionsFuture.get(5, TimeUnit.MILLISECONDS);
        assertEquals(smartActions.size(), 0);
    }

    // Tests for share action extras
    @Test
    public void testShareActionExtras() {
        if (Looper.myLooper() == null) {
            Looper.prepare();
        }

        ScreenshotController.SaveImageInBackgroundData
                data = new ScreenshotController.SaveImageInBackgroundData();
        data.image = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
        data.finisher = null;
        data.mActionsReadyListener = null;
        SaveImageInBackgroundTask task =
                new SaveImageInBackgroundTask(mContext, null, mScreenshotSmartActions, data,
                        ActionTransition::new);

        Notification.Action shareAction = task.createShareAction(mContext, mContext.getResources(),
                Uri.parse("Screenshot_123.png")).get().action;

        Intent intent = shareAction.actionIntent.getIntent();
        assertNotNull(intent);
        Bundle bundle = intent.getExtras();
        assertTrue(bundle.containsKey(ScreenshotController.EXTRA_ID));
        assertTrue(bundle.containsKey(ScreenshotController.EXTRA_SMART_ACTIONS_ENABLED));
        assertEquals(ScreenshotController.ACTION_TYPE_SHARE, shareAction.title);
        assertEquals(Intent.ACTION_SEND, intent.getAction());
    }

    // Tests for edit action extras
    @Test
    public void testEditActionExtras() {
        if (Looper.myLooper() == null) {
            Looper.prepare();
        }

        ScreenshotController.SaveImageInBackgroundData
                data = new ScreenshotController.SaveImageInBackgroundData();
        data.image = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
        data.finisher = null;
        data.mActionsReadyListener = null;
        SaveImageInBackgroundTask task =
                new SaveImageInBackgroundTask(mContext, null, mScreenshotSmartActions, data,
                        ActionTransition::new);

        Notification.Action editAction = task.createEditAction(mContext, mContext.getResources(),
                Uri.parse("Screenshot_123.png")).get().action;

        Intent intent = editAction.actionIntent.getIntent();
        assertNotNull(intent);
        Bundle bundle = intent.getExtras();
        assertTrue(bundle.containsKey(ScreenshotController.EXTRA_ID));
        assertTrue(bundle.containsKey(ScreenshotController.EXTRA_SMART_ACTIONS_ENABLED));
        assertEquals(ScreenshotController.ACTION_TYPE_EDIT, editAction.title);
        assertEquals(Intent.ACTION_EDIT, intent.getAction());
    }

    // Tests for share action extras
    @Test
    public void testDeleteActionExtras() {
        if (Looper.myLooper() == null) {
            Looper.prepare();
        }

        ScreenshotController.SaveImageInBackgroundData
                data = new ScreenshotController.SaveImageInBackgroundData();
        data.image = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
        data.finisher = null;
        data.mActionsReadyListener = null;
        SaveImageInBackgroundTask task =
                new SaveImageInBackgroundTask(mContext, null, mScreenshotSmartActions, data,
                        ActionTransition::new);

        Notification.Action deleteAction = task.createDeleteAction(mContext,
                mContext.getResources(),
                Uri.parse("Screenshot_123.png"));

        Intent intent = deleteAction.actionIntent.getIntent();
        assertNotNull(intent);
        Bundle bundle = intent.getExtras();
        assertTrue(bundle.containsKey(ScreenshotController.EXTRA_ID));
        assertTrue(bundle.containsKey(ScreenshotController.EXTRA_SMART_ACTIONS_ENABLED));
        assertEquals(deleteAction.title, ScreenshotController.ACTION_TYPE_DELETE);
        assertNull(intent.getAction());
    }
}
