/*
 * Copyright (C) 2016 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.providerui.cts;

import static android.provider.cts.ProviderTestUtils.resolveVolumeName;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import android.app.Activity;
import android.app.Instrumentation;
import android.app.UiAutomation;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.UriPermission;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.provider.cts.ProviderTestUtils;
import android.providerui.cts.GetResultActivity.Result;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.BySelector;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.UiObjectNotFoundException;
import android.support.test.uiautomator.UiSelector;
import android.support.test.uiautomator.Until;
import android.system.Os;
import android.text.format.DateUtils;
import android.util.Log;
import android.util.Pair;

import androidx.test.InstrumentationRegistry;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;

@RunWith(Parameterized.class)
public class MediaStoreUiTest {
    private static final String TAG = "MediaStoreUiTest";

    private static final int REQUEST_CODE = 42;
    private static final long TIMEOUT_MILLIS = 30 * DateUtils.SECOND_IN_MILLIS;
    private static final String MEDIA_DOCUMENTS_PROVIDER_AUTHORITY =
            "com.android.providers.media.documents";

    private Instrumentation mInstrumentation;
    private Context mContext;
    private UiDevice mDevice;
    private GetResultActivity mActivity;

    private File mFile;
    private Uri mMediaStoreUri;
    private String mTargetPackageName;
    private String mDocumentsUiPackageId;

    @Parameter(0)
    public String mVolumeName;

    @Parameters
    public static Iterable<? extends Object> data() {
        return ProviderTestUtils.getSharedVolumeNames();
    }

    @Before
    public void setUp() throws Exception {
        mInstrumentation = InstrumentationRegistry.getInstrumentation();
        mContext = InstrumentationRegistry.getTargetContext();
        mDevice = UiDevice.getInstance(mInstrumentation);
        final PackageManager pm = mContext.getPackageManager();
        final Intent intent2 = new Intent(Intent.ACTION_OPEN_DOCUMENT);
        intent2.addCategory(Intent.CATEGORY_OPENABLE);
        intent2.setType("*/*");
        final ResolveInfo ri = pm.resolveActivity(intent2, 0);
        mDocumentsUiPackageId = ri.activityInfo.packageName;

        final Intent intent = new Intent(mContext, GetResultActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        mActivity = (GetResultActivity) mInstrumentation.startActivitySync(intent);
        mInstrumentation.waitForIdleSync();
        mActivity.clearResult();
        mDevice.wakeUp();
    }

    @After
    public void tearDown() throws Exception {
        if (mFile != null) {
            mFile.delete();
        }

        if (mActivity != null) {
            final ContentResolver resolver = mActivity.getContentResolver();
            for (UriPermission permission : resolver.getPersistedUriPermissions()) {
                mActivity.revokeUriPermission(
                        permission.getUri(),
                        Intent.FLAG_GRANT_READ_URI_PERMISSION
                            | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            }
            mActivity.finish();
        }
    }

    @Test
    public void testGetDocumentUri() throws Exception {
        if (!supportsHardware()) return;

        prepareFile();
        clearDocumentsUi();

        final Uri treeUri = acquireAccess(mFile, Environment.DIRECTORY_DOCUMENTS);
        assertNotNull(treeUri);

        final Uri docUri = MediaStore.getDocumentUri(mActivity, mMediaStoreUri);
        assertNotNull(docUri);

        final ContentResolver resolver = mActivity.getContentResolver();

        // Test reading
        final byte[] expected = "TEST".getBytes();
        final byte[] actual = new byte[4];
        try (ParcelFileDescriptor fd = resolver.openFileDescriptor(docUri, "r")) {
            Os.read(fd.getFileDescriptor(), actual, 0, actual.length);
            assertArrayEquals(expected, actual);
        }

        // Test writing
        try (ParcelFileDescriptor fd = resolver.openFileDescriptor(docUri, "wt")) {
            Os.write(fd.getFileDescriptor(), expected, 0, expected.length);
        }
    }

    @Test
    public void testGetDocumentUri_throwsWithoutPermission() throws Exception {
        if (!supportsHardware()) return;

        prepareFile();
        clearDocumentsUi();

        try {
            MediaStore.getDocumentUri(mActivity, mMediaStoreUri);
            fail("Expecting SecurityException.");
        } catch (SecurityException e) {
            // Expected
        }
    }

    @Test
    public void testGetDocumentUri_symmetry_externalStorageProvider() throws Exception {
        if (!supportsHardware()) return;

        prepareFile();
        clearDocumentsUi();

        final Uri treeUri = acquireAccess(mFile, Environment.DIRECTORY_DOCUMENTS);
        Log.v(TAG, "Tree " + treeUri);
        assertNotNull(treeUri);

        final Uri docUri = MediaStore.getDocumentUri(mActivity, mMediaStoreUri);
        Log.v(TAG, "Document " + docUri);
        assertNotNull(docUri);

        final Uri mediaUri = MediaStore.getMediaUri(mActivity, docUri);
        Log.v(TAG, "Media " + mediaUri);
        assertNotNull(mediaUri);

        assertEquals(mMediaStoreUri, mediaUri);
        assertAccessToMediaUri(mediaUri, mFile);
    }

    @Test
    public void testGetMediaUriAccess_mediaDocumentsProvider() throws Exception {
        if (!supportsHardware()) return;

        prepareFile("TEST");
        clearDocumentsUi();
        final Intent intent = new Intent();
        intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("*/*");
        mActivity.startActivityForResult(intent, REQUEST_CODE);
        mDevice.waitForIdle();

        findDocument(mFile.getName()).click();
        final Result result = mActivity.getResult();
        final Uri uri = result.data.getData();
        assertEquals(MEDIA_DOCUMENTS_PROVIDER_AUTHORITY, uri.getAuthority());
        final Uri mediaUri = MediaStore.getMediaUri(mActivity, uri);

        assertAccessToMediaUri(mediaUri, mFile);
    }

    @Test
    public void testOpenFile_onMediaDocumentsProvider_success() throws Exception {
        if (!supportsHardware()) return;

        final String rawText = "TEST";
        // Stage a text file which contains raw text "TEST"
        prepareFile(rawText);
        clearDocumentsUi();
        final Intent intent = new Intent();
        intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("*/*");
        mActivity.startActivityForResult(intent, REQUEST_CODE);
        mDevice.waitForIdle();

        findDocument(mFile.getName()).click();
        final Result result = mActivity.getResult();
        final Uri uri = result.data.getData();
        assertEquals(MEDIA_DOCUMENTS_PROVIDER_AUTHORITY, uri.getAuthority());

        // Test reading
        final byte[] expected = rawText.getBytes();
        final byte[] actual = new byte[4];
        try (ParcelFileDescriptor fd = mContext.getContentResolver()
                .openFileDescriptor(uri, "r")) {
            Os.read(fd.getFileDescriptor(), actual, 0, actual.length);
            assertArrayEquals(expected, actual);
        }

        // Test write and read after it
        final byte[] writtenText = "Hello World".getBytes();
        final byte[] readText = new byte[11];
        try (ParcelFileDescriptor fd = mContext.getContentResolver()
                .openFileDescriptor(uri, "wt")) {
            Os.write(fd.getFileDescriptor(), writtenText, 0, writtenText.length);
        }
        try (ParcelFileDescriptor fd = mContext.getContentResolver()
                .openFileDescriptor(uri, "r")) {
            Os.read(fd.getFileDescriptor(), readText, 0, readText.length);
            assertArrayEquals(writtenText, readText);
        }
    }

    @Test
    public void testOpenFile_onMediaDocumentsProvider_failsWithoutAccess() throws Exception {
        if (!supportsHardware()) return;

        String rawText = "TEST";
        // Read and write grants will be provided to the file associated with this pair.
        // Stages a text file which contains raw text "TEST"
        Pair<Uri, File> uriFilePairWithGrants =  prepareFileAndFetchDetails(rawText);

        clearDocumentsUi();
        final Intent intent = new Intent();
        intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("*/*");
        mActivity.startActivityForResult(intent, REQUEST_CODE);
        mDevice.waitForIdle();

        // Read and write grants will not be provided to the file associated with this pair
        // Stages a text file which contains raw text "TEST"
        Pair<Uri, File> uriFilePairWithoutGrants =  prepareFileAndFetchDetails(rawText);
        // Get access grants
        findDocument(uriFilePairWithGrants.second.getName()).click();
        final Result result = mActivity.getResult();
        final Uri docUriOfFileWithAccess = result.data.getData();
        // Creating doc URI for file by string replacement
        Uri docUriOfFileWithoutAccess = Uri.parse(docUriOfFileWithAccess.toSafeString().replaceAll(
                String.valueOf(ContentUris.parseId(uriFilePairWithGrants.first)),
                String.valueOf(ContentUris.parseId(uriFilePairWithoutGrants.first))));

        try {
            assertEquals(MEDIA_DOCUMENTS_PROVIDER_AUTHORITY, docUriOfFileWithAccess.getAuthority());
            assertEquals(MEDIA_DOCUMENTS_PROVIDER_AUTHORITY,
                    docUriOfFileWithoutAccess.getAuthority());
            // Test reading
            try (ParcelFileDescriptor fd = mContext.getContentResolver().openFileDescriptor(
                    docUriOfFileWithoutAccess, "r")) {
                fail("Expecting security exception as file does not have read grants which "
                        + "are provided through ACTION_OPEN_DOCUMENT intent.");
            } catch (SecurityException expected) {
                // Expected security exception as file does not have read grants
            }
            // Test writing
            try (ParcelFileDescriptor fd = mContext.getContentResolver().openFileDescriptor(
                    docUriOfFileWithoutAccess, "wt")) {
                fail("Expecting security exception as file does not have write grants which "
                        + "are provided through ACTION_OPEN_DOCUMENT intent.");
            } catch (SecurityException expected) {
                // Expected security exception as file does not have write grants
            }
        } finally {
            // Deleting files
            uriFilePairWithGrants.second.delete();
            uriFilePairWithoutGrants.second.delete();
        }
    }

    private void assertAccessToMediaUri(Uri mediaUri, File file) {
        final String[] projection = {MediaStore.MediaColumns.DISPLAY_NAME};
        try (Cursor c = mContext.getContentResolver().query(
                mediaUri, projection, null, null, null)) {
            assertTrue(c.moveToFirst());
            assertEquals(file.getName(), c.getString(0));
        }
    }

    /**
     * Clears the DocumentsUI package data.
     */
    protected void clearDocumentsUi() throws Exception {
        executeShellCommand("pm clear " + getDocumentsUiPackageId());
    }

    private UiObject findDocument(String label) throws UiObjectNotFoundException {
        final UiSelector docList = new UiSelector().resourceId(getDocumentsUiPackageId()
                + ":id/dir_list");

        // Wait for the first list item to appear
        assertTrue("First list item",
                new UiObject(docList.childSelector(new UiSelector()))
                        .waitForExists(TIMEOUT_MILLIS));

        try {
            //Enforce to set the list mode
            //Because UiScrollable can't reach the real bottom (when WEB_LINKABLE_FILE item)
            // in grid mode when screen landscape mode
            new UiObject(new UiSelector().resourceId(getDocumentsUiPackageId()
                    + ":id/sub_menu_list")).click();
            mDevice.waitForIdle();
        }catch (UiObjectNotFoundException e){
            //do nothing, already be in list mode.
        }

        // Repeat swipe gesture to find our item
        // (UiScrollable#scrollIntoView does not seem to work well with SwipeRefreshLayout)
        UiObject targetObject = new UiObject(docList.childSelector(new UiSelector().text(label)));
        UiObject saveButton = findSaveButton();
        int stepLimit = 10;
        while (stepLimit-- > 0) {
            if (targetObject.exists()) {
                boolean targetObjectFullyVisible = !saveButton.exists()
                        || targetObject.getVisibleBounds().bottom
                        <= saveButton.getVisibleBounds().top;
                if (targetObjectFullyVisible) {
                    break;
                }
            }

            mDevice.swipe(/* startX= */ mDevice.getDisplayWidth() / 2,
                    /* startY= */ mDevice.getDisplayHeight() / 2,
                    /* endX= */ mDevice.getDisplayWidth() / 2,
                    /* endY= */ 0,
                    /* steps= */ 40);
        }
        return targetObject;
    }

    private UiObject findSaveButton() throws UiObjectNotFoundException {
        return new UiObject(new UiSelector().resourceId(
                getDocumentsUiPackageId() + ":id/container_save")
                .childSelector(new UiSelector().resourceId("android:id/button1")));
    }

    private String getDocumentsUiPackageId() {
        return mDocumentsUiPackageId;
    }

    private boolean supportsHardware() {
        final PackageManager pm = mContext.getPackageManager();
        return !pm.hasSystemFeature("android.hardware.type.television")
                && !pm.hasSystemFeature("android.hardware.type.watch")
                && !pm.hasSystemFeature("android.hardware.type.automotive");
    }

    public File getVolumePath(String volumeName) {
        return mContext.getSystemService(StorageManager.class)
                .getStorageVolume(MediaStore.Files.getContentUri(volumeName)).getDirectory();
    }

    private void prepareFile() throws Exception {
        final File dir = new File(getVolumePath(resolveVolumeName(mVolumeName)),
                Environment.DIRECTORY_DOCUMENTS);
        final File file = new File(dir, "cts" + System.nanoTime() + ".txt");

        mFile = stageFile(R.raw.text, file);
        mMediaStoreUri = MediaStore.scanFile(mContext.getContentResolver(), mFile);

        Log.v(TAG, "Staged " + mFile + " as " + mMediaStoreUri);
    }

    private void prepareFile(String rawText) throws Exception {
        final File dir = new File(getVolumePath(resolveVolumeName(mVolumeName)),
                Environment.DIRECTORY_DOCUMENTS);
        final File file = new File(dir, "cts" + System.nanoTime() + ".txt");

        mFile = stageFileWithRawText(rawText, file);
        mMediaStoreUri = MediaStore.scanFile(mContext.getContentResolver(), mFile);

        Log.v(TAG, "Staged " + mFile + " as " + mMediaStoreUri);
    }

    private Pair<Uri, File> prepareFileAndFetchDetails(String rawText) throws Exception {
        final File dir = new File(getVolumePath(resolveVolumeName(mVolumeName)),
                Environment.DIRECTORY_DOCUMENTS);
        final File file = new File(dir, "cts" + System.nanoTime() + ".txt");

        File stagedFile = stageFileWithRawText(rawText, file);

        Uri uri = MediaStore.scanFile(mContext.getContentResolver(), stagedFile);
        Log.v(TAG, "Staged " + stagedFile + " as " + uri);
        return Pair.create(uri, stagedFile);
    }

    private void assertToolbarTitleEquals(String targetPackageName, String label)
            throws UiObjectNotFoundException {
        final UiSelector toolbarUiSelector = new UiSelector().resourceId(
                targetPackageName + ":id/toolbar");
        final UiSelector titleTextSelector = new UiSelector().className(
                "android.widget.TextView").text(label);
        final UiObject title = new UiObject(toolbarUiSelector.childSelector(titleTextSelector));

        assertTrue(title.waitForExists(TIMEOUT_MILLIS));
    }

    private Uri acquireAccess(File file, String directoryName) throws Exception {
        StorageManager storageManager =
                (StorageManager) mActivity.getSystemService(Context.STORAGE_SERVICE);

        // Request access from DocumentsUI
        final StorageVolume volume = storageManager.getStorageVolume(file);
        final Intent intent = volume.createOpenDocumentTreeIntent();

        // launch the directory directly to avoid unexpected UiObject not found issue
        final Uri rootUri = intent.getParcelableExtra(DocumentsContract.EXTRA_INITIAL_URI);
        final String rootId = DocumentsContract.getRootId(rootUri);
        final String documentId = rootId + ":" + directoryName;
        intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI,
                DocumentsContract.buildDocumentUri(rootUri.getAuthority(), documentId));
        mActivity.startActivityForResult(intent, REQUEST_CODE);

        if (mTargetPackageName == null) {
            mTargetPackageName = getTargetPackageName(mActivity);
        }
        mDevice.waitForIdle();
        assertToolbarTitleEquals(mTargetPackageName, directoryName);

        // Granting the access
        BySelector buttonPanelSelector = By.pkg(mTargetPackageName)
                .res(mTargetPackageName + ":id/container_save");
        mDevice.wait(Until.hasObject(buttonPanelSelector), TIMEOUT_MILLIS);
        final UiObject2 buttonPanel = mDevice.findObject(buttonPanelSelector);
        final UiObject2 allowButton = buttonPanel.findObject(By.res("android:id/button1"));
        allowButton.click();
        mDevice.waitForIdle();

        // Granting the access by click "allow" in confirm dialog
        final BySelector dialogButtonPanelSelector = By.pkg(mTargetPackageName)
                .res(mTargetPackageName + ":id/buttonPanel");
        mDevice.wait(Until.hasObject(dialogButtonPanelSelector), TIMEOUT_MILLIS);
        final UiObject2 positiveButton = mDevice.findObject(dialogButtonPanelSelector)
                .findObject(By.res("android:id/button1"));
        positiveButton.click();
        mDevice.waitForIdle();

        // Check granting result and take persistent permission
        final Result result = mActivity.getResult();
        assertEquals(Activity.RESULT_OK, result.resultCode);

        final Intent resultIntent = result.data;
        final Uri resultUri = resultIntent.getData();
        final int flags = resultIntent.getFlags()
                & (Intent.FLAG_GRANT_READ_URI_PERMISSION
                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        mActivity.getContentResolver().takePersistableUriPermission(resultUri, flags);
        return resultUri;
    }

    private static String getTargetPackageName(Context context) {
        final PackageManager pm = context.getPackageManager();

        final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("*/*");
        final ResolveInfo ri = pm.resolveActivity(intent, 0);
        return ri.activityInfo.packageName;
    }

    // TODO: replace with ProviderTestUtils
    static String executeShellCommand(String command) throws IOException {
        return executeShellCommand(command,
                InstrumentationRegistry.getInstrumentation().getUiAutomation());
    }

    // TODO: replace with ProviderTestUtils
    static String executeShellCommand(String command, UiAutomation uiAutomation)
            throws IOException {
        Log.v(TAG, "$ " + command);
        ParcelFileDescriptor pfd = uiAutomation.executeShellCommand(command.toString());
        BufferedReader br = null;
        try (InputStream in = new FileInputStream(pfd.getFileDescriptor());) {
            br = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
            String str = null;
            StringBuilder out = new StringBuilder();
            while ((str = br.readLine()) != null) {
                Log.v(TAG, "> " + str);
                out.append(str);
            }
            return out.toString();
        } finally {
            if (br != null) {
                br.close();
            }
        }
    }

    // TODO: replace with ProviderTestUtils
    static File stageFile(int resId, File file) throws IOException {
        // The caller may be trying to stage into a location only available to
        // the shell user, so we need to perform the entire copy as the shell
        final Context context = InstrumentationRegistry.getTargetContext();
        final File dir = file.getParentFile();
        dir.mkdirs();
        if (!dir.exists()) {
            throw new FileNotFoundException("Failed to create parent for " + file);
        }
        try (InputStream source = context.getResources().openRawResource(resId);
             OutputStream target = new FileOutputStream(file)) {
            FileUtils.copy(source, target);
        }
        return file;
    }

    static File stageFileWithRawText(String rawText, File file) throws IOException {
        final File dir = file.getParentFile();
        dir.mkdirs();
        if (!dir.exists()) {
            throw new FileNotFoundException("Failed to create parent for " + file);
        }
        try (InputStream source = new ByteArrayInputStream(
                rawText.getBytes(StandardCharsets.UTF_8));
             OutputStream target = new FileOutputStream(file)) {
            FileUtils.copy(source, target);
        }
        return file;
    }
}
