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

import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.Manifest.permission.CAMERA;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.RECORD_AUDIO;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;

import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.UriPermission;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.media.ExifInterface;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.os.SystemClock;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
import android.provider.MediaStore;
import android.provider.cts.GetResultActivity.Result;
import android.support.test.InstrumentationRegistry;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.BySelector;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.UiSelector;
import android.support.test.uiautomator.Until;
import android.test.InstrumentationTestCase;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.KeyEvent;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import androidx.core.content.FileProvider;

public class MediaStoreUiTest extends InstrumentationTestCase {
    private static final String TAG = "MediaStoreUiTest";

    private static final int REQUEST_CODE = 42;
    private static final String CONTENT = "Test";

    private UiDevice mDevice;
    private GetResultActivity mActivity;

    private File mFile;
    private Uri mMediaStoreUri;

    @Override
    public void setUp() throws Exception {
        mDevice = UiDevice.getInstance(getInstrumentation());

        final Context context = getInstrumentation().getContext();
        mActivity = launchActivity(context.getPackageName(), GetResultActivity.class, null);
        mActivity.clearResult();
    }

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

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

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

        prepareFile();

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

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

        final ContentResolver resolver = mActivity.getContentResolver();
        try (ParcelFileDescriptor fd = resolver.openFileDescriptor(docUri, "rw")) {
            // Test reading
            try (final BufferedReader reader =
                         new BufferedReader(new FileReader(fd.getFileDescriptor()))) {
                assertEquals(CONTENT, reader.readLine());
            }

            // Test writing
            try (final OutputStream out = new FileOutputStream(fd.getFileDescriptor())) {
                out.write(CONTENT.getBytes());
            }
        }
    }

    public void testGetDocumentUri_ThrowsWithoutPermission() throws Exception {
        if (!supportsHardware()) return;

        prepareFile();

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

    private void maybeClick(UiSelector sel) {
        try { mDevice.findObject(sel).click(); } catch (Throwable ignored) { }
    }

    private void maybeClick(BySelector sel) {
        try { mDevice.findObject(sel).click(); } catch (Throwable ignored) { }
    }

    private void maybeGrantRuntimePermission(String pkg, Set<String> requested, String permission) {
        if (requested.contains(permission)) {
            InstrumentationRegistry.getInstrumentation().getUiAutomation()
                    .grantRuntimePermission(pkg, permission);
        }
    }

    /**
     * Verify that whoever handles {@link MediaStore#ACTION_IMAGE_CAPTURE} can
     * correctly write the contents into a passed {@code content://} Uri.
     */
    public void testImageCapture() throws Exception {
        final Context context = getInstrumentation().getContext();
        if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
            Log.d(TAG, "Skipping due to lack of camera");
            return;
        }

        final File targetDir = new File(context.getFilesDir(), "debug");
        final File target = new File(targetDir, "capture.jpg");

        targetDir.mkdirs();
        assertFalse(target.exists());

        final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        intent.putExtra(MediaStore.EXTRA_OUTPUT,
                FileProvider.getUriForFile(context, "android.provider.cts.fileprovider", target));

        // Figure out who is going to answer the phone
        final ResolveInfo ri = context.getPackageManager().resolveActivity(intent, 0);
        final String pkg = ri.activityInfo.packageName;
        Log.d(TAG, "We're probably launching " + ri);

        final PackageInfo pi = context.getPackageManager().getPackageInfo(pkg,
                PackageManager.GET_PERMISSIONS);
        final Set<String> req = new HashSet<>();
        req.addAll(Arrays.asList(pi.requestedPermissions));

        // Grant them all the permissions they might want
        maybeGrantRuntimePermission(pkg, req, CAMERA);
        maybeGrantRuntimePermission(pkg, req, ACCESS_COARSE_LOCATION);
        maybeGrantRuntimePermission(pkg, req, ACCESS_FINE_LOCATION);
        maybeGrantRuntimePermission(pkg, req, RECORD_AUDIO);
        maybeGrantRuntimePermission(pkg, req, READ_EXTERNAL_STORAGE);
        maybeGrantRuntimePermission(pkg, req, WRITE_EXTERNAL_STORAGE);
        SystemClock.sleep(DateUtils.SECOND_IN_MILLIS);

        mActivity.startActivityForResult(intent, REQUEST_CODE);
        mDevice.waitForIdle();

        // To ensure camera app is launched
        SystemClock.sleep(5 * DateUtils.SECOND_IN_MILLIS);

        // Try a couple different strategies for taking a photo: first take a
        // photo and confirm using hardware keys
        mDevice.pressKeyCode(KeyEvent.KEYCODE_CAMERA);
        mDevice.waitForIdle();
        SystemClock.sleep(5 * DateUtils.SECOND_IN_MILLIS);
        mDevice.pressKeyCode(KeyEvent.KEYCODE_DPAD_CENTER);
        mDevice.waitForIdle();

        // Maybe that gave us a result?
        Result result = mActivity.getResult(15, TimeUnit.SECONDS);
        Log.d(TAG, "First pass result was " + result);

        // Hrm, that didn't work; let's try an alternative approach of digging
        // around for a shutter button
        if (result == null) {
            maybeClick(new UiSelector().resourceId(pkg + ":id/shutter_button"));
            mDevice.waitForIdle();
            SystemClock.sleep(5 * DateUtils.SECOND_IN_MILLIS);
            maybeClick(new UiSelector().resourceId(pkg + ":id/shutter_button"));
            mDevice.waitForIdle();
            maybeClick(new UiSelector().resourceId(pkg + ":id/done_button"));
            mDevice.waitForIdle();

            result = mActivity.getResult(15, TimeUnit.SECONDS);
            Log.d(TAG, "Second pass result was " + result);
        }

        // Grr, let's try hunting around even more
        if (result == null) {
            maybeClick(By.pkg(pkg).descContains("Capture"));
            mDevice.waitForIdle();
            SystemClock.sleep(5 * DateUtils.SECOND_IN_MILLIS);
            maybeClick(By.pkg(pkg).descContains("Done"));
            mDevice.waitForIdle();

            result = mActivity.getResult(15, TimeUnit.SECONDS);
            Log.d(TAG, "Third pass result was " + result);
        }

        assertNotNull("Expected to get a IMAGE_CAPTURE result; your camera app should "
                + "respond to the CAMERA and DPAD_CENTER keycodes", result);

        assertTrue("exists", target.exists());
        assertTrue("has data", target.length() > 65536);

        // At the very least we expect photos generated by the device to have
        // sane baseline EXIF data
        final ExifInterface exif = new ExifInterface(new FileInputStream(target));
        assertAttribute(exif, ExifInterface.TAG_MAKE);
        assertAttribute(exif, ExifInterface.TAG_MODEL);
        assertAttribute(exif, ExifInterface.TAG_DATETIME);
    }

    private static void assertAttribute(ExifInterface exif, String tag) {
        final String res = exif.getAttribute(tag);
        if (res == null || res.length() == 0) {
            Log.d(TAG, "Expected valid EXIF tag for tag " + tag);
        }
    }

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

    private void prepareFile() throws Exception {
        assertEquals(Environment.MEDIA_MOUNTED, Environment.getExternalStorageState());

        final File documents =
                Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS);
        documents.mkdirs();
        assertTrue(documents.isDirectory());

        mFile = new File(documents, "test.jpg");
        try (OutputStream os = new FileOutputStream(mFile)) {
            os.write(CONTENT.getBytes());
        }

        final CountDownLatch latch = new CountDownLatch(1);
        MediaScannerConnection.scanFile(
                mActivity,
                new String[]{ mFile.getAbsolutePath() },
                new String[]{ "image/jpeg" },
                (String path, Uri uri) -> onScanCompleted(uri, latch)
        );
        assertTrue(
                "MediaScanner didn't finish scanning in 30s.", latch.await(30, TimeUnit.SECONDS));
    }

    private void onScanCompleted(Uri uri, CountDownLatch latch) {
        mMediaStoreUri = uri;
        latch.countDown();
    }

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

        // Request access from DocumentsUI
        final StorageVolume volume = storageManager.getStorageVolume(file);
        final Intent intent = volume.createAccessIntent(directoryName);
        mActivity.startActivityForResult(intent, REQUEST_CODE);

        // Granting the access
        BySelector buttonPanelSelector = By.pkg("com.android.documentsui")
                .res("android:id/buttonPanel");
        mDevice.wait(Until.hasObject(buttonPanelSelector), 30 * DateUtils.SECOND_IN_MILLIS);
        final UiObject2 buttonPanel = mDevice.findObject(buttonPanelSelector);
        final UiObject2 allowButton = buttonPanel.findObject(By.res("android:id/button1"));
        allowButton.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;
    }
}
