/*
 * 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.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(() -> mSmartActionsProvider);
        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 =
                new ScreenshotNotificationSmartActionsProvider();
        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, mSmartActionsProvider);

        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, mSmartActionsProvider);

        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, mSmartActionsProvider);

        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());
    }
}
