/*
 * Copyright (C) 2021 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 android.photopicker.cts;

import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertPickerUriFormat;
import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertRedactedReadOnlyAccess;
import static android.photopicker.cts.util.PhotoPickerFilesUtils.createImages;
import static android.photopicker.cts.util.PhotoPickerFilesUtils.deleteMedia;
import static android.photopicker.cts.util.PhotoPickerUiUtils.SHORT_TIMEOUT;
import static android.photopicker.cts.util.PhotoPickerUiUtils.findAddButton;
import static android.photopicker.cts.util.PhotoPickerUiUtils.findItemList;
import static android.photopicker.cts.util.PhotoPickerUiUtils.findProfileButton;

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

import android.content.ClipData;
import android.content.Intent;
import android.net.Uri;
import android.provider.MediaStore;

import androidx.test.filters.SdkSuppress;
import androidx.test.uiautomator.UiObject;
import androidx.test.uiautomator.UiSelector;

import com.android.bedstead.harrier.BedsteadJUnit4;
import com.android.bedstead.harrier.DeviceState;
import com.android.bedstead.harrier.annotations.EnsureHasWorkProfile;
import com.android.bedstead.harrier.annotations.RequireRunOnWorkProfile;

import org.junit.After;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.ArrayList;
import java.util.List;

/**
 * Photo Picker Device only tests for cross profile interaction flows.
 */
@RunWith(BedsteadJUnit4.class)
public class PhotoPickerCrossProfileTest extends PhotoPickerBaseTest {
    @ClassRule @Rule
    public static final DeviceState sDeviceState = new DeviceState();

    private List<Uri> mUriList = new ArrayList<>();

    @After
    public void tearDown() throws Exception {
        for (Uri uri : mUriList) {
            deleteMedia(uri, mContext);
        }
        mUriList.clear();
        mActivity.finish();
    }

    /**
     * ACTION_PICK_IMAGES is allowlisted by default from work to personal. This got allowlisted
     * in a platform code change and is available Android T onwards.
     */
    @Test
    @RequireRunOnWorkProfile
    @SdkSuppress(minSdkVersion = 32, codeName = "T")
    public void testWorkApp_canAccessPersonalProfileContents() throws Exception {
        final int imageCount = 2;
        createImages(imageCount, sDeviceState.primaryUser().id(), mUriList);

        Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
        intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, imageCount);
        mActivity.startActivityForResult(intent, REQUEST_CODE);

        // Click the profile button to change to personal profile
        final UiObject profileButton = findProfileButton();
        profileButton.click();
        mDevice.waitForIdle();

        final List<UiObject> itemList = findItemList(imageCount);
        final int itemCount = itemList.size();
        assertThat(itemCount).isEqualTo(imageCount);
        for (int i = 0; i < itemCount; i++) {
            final UiObject item = itemList.get(i);
            item.click();
            mDevice.waitForIdle();
        }

        final UiObject addButton = findAddButton();
        addButton.click();
        mDevice.waitForIdle();

        final ClipData clipData = mActivity.getResult().data.getClipData();
        final int count = clipData.getItemCount();
        assertThat(count).isEqualTo(imageCount);
        for (int i = 0; i < count; i++) {
            Uri uri = clipData.getItemAt(i).getUri();
            assertPickerUriFormat(uri, sDeviceState.primaryUser().id());
            assertRedactedReadOnlyAccess(uri);
        }
    }

    /**
     * ACTION_PICK_IMAGES is allowlisted by default from work to personal. This got allowlisted
     * in a platform code change and is available Android T onwards. Before that it needs to be
     * explicitly allowlisted by the device admin.
     */
    @Test
    @RequireRunOnWorkProfile
    @SdkSuppress(maxSdkVersion = 31, codeName = "S")
    public void testWorkApp_cannotAccessPersonalProfile_beforeT() throws Exception {
        assertBlockedByAdmin(/* isInvokedFromWorkProfile */ true);
    }

    /**
     * ACTION_PICK_IMAGES is allowlisted by default from work to personal only (not vice-a-versa)
     */
    @Test
    @EnsureHasWorkProfile
    public void testPersonalApp_cannotAccessWorkProfile_default() throws Exception {
        assertBlockedByAdmin(/* isInvokedFromWorkProfile */ false);
    }

    private void assertBlockedByAdmin(boolean isInvokedFromWorkProfile) throws Exception {
        Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
        intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit());
        mActivity.startActivityForResult(intent, REQUEST_CODE);

        // Click the profile button to change to work profile
        final UiObject profileButton = findProfileButton();
        profileButton.click();
        mDevice.waitForIdle();

        assertBlockedByAdminDialog(isInvokedFromWorkProfile);
    }

    private void assertBlockedByAdminDialog(boolean isInvokedFromWorkProfile) {
        final String dialogTitle = "Blocked by your admin";
        assertWithMessage("Timed out while waiting for blocked by admin dialog to appear")
                .that(new UiObject(new UiSelector().textContains(dialogTitle))
                        .waitForExists(SHORT_TIMEOUT))
                .isTrue();

        final String dialogDescription;
        if (isInvokedFromWorkProfile) {
            dialogDescription = "Accessing personal data from a work app is not permitted";
        } else {
            dialogDescription = "Accessing work data from a personal app is not permitted";
        }
        assertWithMessage("Blocked by admin description is not as expected")
                .that(new UiObject(new UiSelector().textContains(dialogDescription)).exists())
                .isTrue();
    }
}
