/*
 * Copyright (C) 2012 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 com.android.cts.provider.R;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.cts.util.FileCopyHelper;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.os.SystemClock;
import android.provider.MediaStore;
import android.provider.MediaStore.MediaColumns;
import android.test.AndroidTestCase;
import android.util.Log;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class MediaStore_FilesTest extends AndroidTestCase {

    private ContentResolver mResolver;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mResolver = mContext.getContentResolver();
        cleanup();
    }

    @Override
    protected void tearDown() throws Exception {
        super.tearDown();
        cleanup();
    }

    void cleanup() {
        final String testName = getClass().getCanonicalName();
        mResolver.delete(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                "_data LIKE ?1", new String[] {"%" + testName + "%"});
        File ext = Environment.getExternalStorageDirectory();
        File[] junk = ext.listFiles(new FilenameFilter() {

            @Override
            public boolean accept(File dir, String filename) {
                return filename.contains(testName);
            }
        });
        for (File f: junk) {
            deleteAll(f);
        }
    }

    void deleteAll(File f) {
        if (f.isDirectory()) {
            File [] sub = f.listFiles();
            for (File s: sub) {
                deleteAll(s);
            }
        }
        f.delete();
    }

    public void testGetContentUri() {
        String volumeName = MediaStoreAudioTestHelper.EXTERNAL_VOLUME_NAME;
        Uri allFilesUri = MediaStore.Files.getContentUri(volumeName);

        // Get the current file count. We will check if this increases after
        // adding a file to the provider.
        int fileCount = getFileCount(allFilesUri);

        // Check that inserting empty values causes an exception.
        ContentValues values = new ContentValues();
        try {
            mResolver.insert(allFilesUri, values);
            fail("Should throw an exception");
        } catch (IllegalArgumentException e) {
            // Expecting an exception
        }

        // Add a path for a file and check that the returned uri appends a
        // path properly.
        String dataPath = "does_not_really_exist.txt";
        values.put(MediaColumns.DATA, dataPath);
        Uri fileUri = mResolver.insert(allFilesUri, values);
        long fileId = ContentUris.parseId(fileUri);
        assertEquals(fileUri, ContentUris.withAppendedId(allFilesUri, fileId));

        // Check that getContentUri with the file id produces the same url
        Uri rowUri = MediaStore.Files.getContentUri(volumeName, fileId);
        assertEquals(fileUri, rowUri);

        // Check that the file count has increased.
        int newFileCount = getFileCount(allFilesUri);
        assertEquals(fileCount + 1, newFileCount);

        // Check that the path we inserted was stored properly.
        assertStringColumn(fileUri, MediaColumns.DATA, dataPath);

        // Update the path and check that the database changed.
        String updatedPath = "still_does_not_exist.txt";
        values.put(MediaColumns.DATA, updatedPath);
        assertEquals(1, mResolver.update(fileUri, values, null, null));
        assertStringColumn(fileUri, MediaColumns.DATA, updatedPath);

        // check that inserting a duplicate entry fails
        Uri foo = mResolver.insert(allFilesUri, values);
        assertNull(foo);

        // Delete the file and observe that the file count decreased.
        assertEquals(1, mResolver.delete(fileUri, null, null));
        assertEquals(fileCount, getFileCount(allFilesUri));

        // Make sure the deleted file is not returned by the cursor.
        Cursor cursor = mResolver.query(fileUri, null, null, null, null);
        try {
            assertFalse(cursor.moveToNext());
        } finally {
            cursor.close();
        }

        // insert file and check its parent
        values.clear();
        try {
            String b = mContext.getExternalFilesDir(Environment.DIRECTORY_MUSIC).getCanonicalPath();
            values.put(MediaColumns.DATA, b + "/testing");
            fileUri = mResolver.insert(allFilesUri, values);
            cursor = mResolver.query(fileUri, new String[] { MediaStore.Files.FileColumns.PARENT },
                    null, null, null);
            assertEquals(1, cursor.getCount());
            cursor.moveToFirst();
            long parentid = cursor.getLong(0);
            assertTrue("got 0 parent for non root file", parentid != 0);

            cursor.close();
            cursor = mResolver.query(ContentUris.withAppendedId(allFilesUri, parentid),
                    new String[] { MediaColumns.DATA }, null, null, null);
            assertEquals(1, cursor.getCount());
            cursor.moveToFirst();
            String parentPath = cursor.getString(0);
            assertEquals(b, parentPath);

            mResolver.delete(fileUri, null, null);
        } catch (IOException e) {
            fail(e.getMessage());
        } finally {
            cursor.close();
        }
    }

    public void testCaseSensitivity() throws IOException {
        String fileDir = Environment.getExternalStorageDirectory() +
                "/" + getClass().getCanonicalName();
        String fileName = fileDir + "/Test.Mp3";
        writeFile(R.raw.testmp3, fileName);

        String volumeName = MediaStoreAudioTestHelper.EXTERNAL_VOLUME_NAME;
        Uri allFilesUri = MediaStore.Files.getContentUri(volumeName);
        ContentValues values = new ContentValues();
        values.put(MediaColumns.DATA, fileDir + "/test.mp3");
        Uri fileUri = mResolver.insert(allFilesUri, values);
        try {
            ParcelFileDescriptor pfd = mResolver.openFileDescriptor(fileUri, "r");
            pfd.close();
        } finally {
            mResolver.delete(fileUri, null, null);
            new File(fileName).delete();
            new File(fileDir).delete();
        }
    }

    String realPathFor(ParcelFileDescriptor pfd) {
        File real = new File("/proc/self/fd/" + pfd.getFd());
        try {
            return real.getCanonicalPath();
        } catch (IOException e) {
            return null;
        }
    }

    public void testAccess() throws IOException {
        // clean up from previous run
        mResolver.delete(MediaStore.Images.Media.INTERNAL_CONTENT_URI,
                "_data NOT LIKE ?", new String[] { "/system/%" } );

        // insert some dummy starter data into the provider
        ContentValues values = new ContentValues();
        values.put(MediaStore.Images.Media.DISPLAY_NAME, "My Bitmap");
        values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
        values.put(MediaStore.Images.Media.DATA, "/foo/bar/dummy.jpg");
        Uri uri = mResolver.insert(MediaStore.Images.Media.INTERNAL_CONTENT_URI, values);

        // point _data at directory and try to get an fd for it
        values = new ContentValues();
        values.put("_data", "/data/media");
        mResolver.update(uri, values, null, null);
        ParcelFileDescriptor pfd = null;
        try {
            pfd = mResolver.openFileDescriptor(uri, "r");
            pfd.close();
            fail("shouldn't be here");
        } catch (FileNotFoundException e) {
            // expected
        }

        // try to create a file in a place we don't have access to
        values = new ContentValues();
        values.put("_data", "/data/media/test.dat");
        mResolver.update(uri, values, null, null);
        try {
            pfd = mResolver.openFileDescriptor(uri, "w");
            pfd.close();
            fail("shouldn't be here");
        } catch (FileNotFoundException e) {
            // expected
        }
        // read file back
        try {
            pfd = mResolver.openFileDescriptor(uri, "r");
            pfd.close();
            fail("shouldn't be here");
        } catch (FileNotFoundException e) {
            // expected
        }

        // point _data at media database and read it
        values = new ContentValues();
        values.put("_data", "/data/data/com.android.providers.media/databases/internal.db");
        mResolver.update(uri, values, null, null);
        try {
            pfd = mResolver.openFileDescriptor(uri, "r");
            pfd.close();
            fail("shouldn't be here");
        } catch (FileNotFoundException e) {
            // expected
        }

        // Insert a private file into the database. Since it's private, the media provider won't
        // be able to open it
        FileOutputStream fos = mContext.openFileOutput("dummy.dat", Context.MODE_PRIVATE);
        fos.write(0);
        fos.close();
        File path = mContext.getFileStreamPath("dummy.dat");
        values = new ContentValues();
        values.put("_data", path.getAbsolutePath());

        mResolver.update(uri, values, null, null);
        try {
            pfd = mResolver.openFileDescriptor(uri, "r");
            pfd.close();
            fail("shouldn't be here");
        } catch (FileNotFoundException e) {
            // expected
        }
        // now make the file world-readable
        fos = mContext.openFileOutput("dummy.dat", Context.MODE_WORLD_READABLE);
        fos.write(0);
        fos.close();
        try {
            pfd = mResolver.openFileDescriptor(uri, "r");
            pfd.close();
        } catch (FileNotFoundException e) {
            fail("failed to open file");
        }
        path.delete();

        File sdfile = null;
        if (Environment.isExternalStorageEmulated()) {
            // create file on sdcard and check access via real path
            String fileDir = Environment.getExternalStorageDirectory() +
                    "/" + getClass().getCanonicalName() + "/test.mp3";
            sdfile = new File(fileDir);
            writeFile(R.raw.testmp3, sdfile.getCanonicalPath());
            assertTrue(sdfile.exists());
            values = new ContentValues();
            values.put("_data", sdfile.getCanonicalPath());
            mResolver.update(uri, values, null, null);
            try {
                pfd = mResolver.openFileDescriptor(uri, "r");

                // get the real path from the file descriptor (this relies on the media provider
                // having opened the path via the real path instead of the emulated path).
                values = new ContentValues();
                values.put("_data", realPathFor(pfd));
                mResolver.update(uri, values, null, null);
                pfd.close();

                // we shouldn't be able to access this
                try {
                    pfd = mResolver.openFileDescriptor(uri, "r");
                    fail("shouldn't have fd for " + realPathFor(pfd));
                } catch (FileNotFoundException e) {
                    // expected
                } finally {
                    pfd.close();
                }
            } catch (FileNotFoundException e) {
                fail("couldn't open file");
            }
        }

        // clean up
        assertEquals(1, mResolver.delete(uri, null, null));
        if (sdfile != null) {
            assertEquals(true, sdfile.delete());
        }

        // test secondary storage if present
        List<File> allpaths = getSecondaryPackageSpecificPaths(mContext);
        List<String> trimmedPaths = new ArrayList<String>();

        for (File extpath: allpaths) {
            assertNotNull("Valid media must be inserted during CTS", extpath);
            assertEquals("Valid media must be inserted for " + extpath
                    + " during CTS", Environment.MEDIA_MOUNTED,
                    Environment.getStorageState(extpath));

            File child = extpath;
            while (true) {
                File parent = child.getParentFile();
                if (parent == null) {
                    fail("didn't expect to be here");
                }
                if (!Environment.MEDIA_MOUNTED.equals(Environment.getStorageState(parent))) {
                    // we went past the root
                    String abspath = child.getAbsolutePath();
                    if (!trimmedPaths.contains(abspath)) {
                        trimmedPaths.add(abspath);
                    }
                    break;
                }
                child = parent;
            }
        }

        String fileDir = Environment.getExternalStorageDirectory() +
                "/" + getClass().getCanonicalName() + "-" + SystemClock.elapsedRealtime();
        String fileName = fileDir + "/TestSecondary.Mp3";
        writeFile(R.raw.testmp3_2, fileName); // file without album art


        // insert temp file
        values = new ContentValues();
        values.put(MediaStore.Audio.Media.DATA, fileName);
        values.put(MediaStore.Audio.Media.ARTIST, "Artist-" + SystemClock.elapsedRealtime());
        values.put(MediaStore.Audio.Media.ALBUM, "Album-" + SystemClock.elapsedRealtime());
        values.put(MediaStore.Audio.Media.MIME_TYPE, "audio/mp3");
        Uri fileUri = mResolver.insert(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, values);
        // give media provider some time to realize there's no album art
        //SystemClock.sleep(1000);
        // get its album id
        Cursor c = mResolver.query(fileUri, new String[] { MediaStore.Audio.Media.ALBUM_ID},
                null, null, null);
        assertTrue(c.moveToFirst());
        int albumid = c.getInt(0);
        Uri albumArtUriBase = Uri.parse("content://media/external/audio/albumart");
        Uri albumArtUri = ContentUris.withAppendedId(albumArtUriBase, albumid);
        try {
            pfd = mResolver.openFileDescriptor(albumArtUri, "r");
            fail("no album art, shouldn't be here. Got: " + realPathFor(pfd));
        } catch (Exception e) {
            // expected
        }

        // replace file with one that has album art
        writeFile(R.raw.testmp3, fileName); // file with album art

        for (String s: trimmedPaths) {
            File dir = new File(s + "/foobardir-" + SystemClock.elapsedRealtime());
            assertFalse("please remove " + dir.getAbsolutePath()
                    + " before running", dir.exists());
            File file = new File(dir, "foobar");
            values = new ContentValues();
            values.put(MediaStore.Audio.Media.ALBUM_ID, albumid);
            values.put(MediaStore.Audio.Media.DATA, file.getAbsolutePath());
            mResolver.insert(albumArtUriBase, values);
            try {
                pfd = mResolver.openFileDescriptor(albumArtUri, "r");
                fail("shouldn't have fd for album " + albumid + ", got " + realPathFor(pfd));
            } catch (Exception e) {
                // expected
            } finally {
                pfd.close();
            }
            assertFalse(dir.getAbsolutePath() + " was created", dir.exists());
        }
        mResolver.delete(fileUri, null, null);
        new File(fileName).delete();

        // try creating files in root
        for (String s: trimmedPaths) {
            File dir = new File(s);
            File file = new File(dir, "foobar.jpg");

            values = new ContentValues();
            values.put(MediaStore.Files.FileColumns.DATA, file.getAbsolutePath());
            fileUri = mResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
            assertNotNull(fileUri);

            // check that adding the file doesn't cause it to be created
            assertFalse(file.exists());

            // check if opening the file for write works
            try {
                mResolver.openOutputStream(fileUri).close();
                fail("shouldn't have been able to create output stream");
            } catch (SecurityException e) {
                // expected
            }
            // check that deleting the file doesn't cause it to be created
            mResolver.delete(fileUri, null, null);
            assertFalse(file.exists());
        }

        // try creating files in new subdir
        for (String s: trimmedPaths) {
            File dir = new File(s + "/foobardir");
            File file = new File(dir, "foobar.jpg");

            values = new ContentValues();
            values.put(MediaStore.Files.FileColumns.DATA, dir.getAbsolutePath());

            Uri dirUri = mResolver.insert(MediaStore.Files.getContentUri("external"), values);
            assertNotNull(dirUri);

            values = new ContentValues();
            values.put(MediaStore.Files.FileColumns.DATA, file.getAbsolutePath());
            fileUri = mResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
            assertNotNull(fileUri);

            // check that adding the file or its folder didn't cause either one to be created
            assertFalse(dir.exists());
            assertFalse(file.exists());

            // check if opening the file for write works
            try {
                mResolver.openOutputStream(fileUri).close();
                fail("shouldn't have been able to create output stream");
            } catch (SecurityException e) {
                // expected
            }
            // check that deleting the file or its folder doesn't cause either one to be created
            mResolver.delete(fileUri, null, null);
            assertFalse(dir.exists());
            assertFalse(file.exists());
            mResolver.delete(dirUri, null, null);
            assertFalse(dir.exists());
            assertFalse(file.exists());
        }
    }

    public static List<File> getSecondaryPackageSpecificPaths(Context context) {
        final List<File> paths = new ArrayList<File>();
        Collections.addAll(paths, dropFirst(context.getExternalCacheDirs()));
        Collections.addAll(paths, dropFirst(context.getExternalFilesDirs(null)));
        Collections.addAll(
                paths, dropFirst(context.getExternalFilesDirs(Environment.DIRECTORY_PICTURES)));
        Collections.addAll(paths, dropFirst(context.getObbDirs()));
        return paths;
    }

    private static File[] dropFirst(File[] before) {
        final File[] after = new File[before.length - 1];
        System.arraycopy(before, 1, after, 0, after.length);
        return after;
    }

    private void writeFile(int resid, String path) throws IOException {
        File out = new File(path);
        File dir = out.getParentFile();
        dir.mkdirs();
        FileCopyHelper copier = new FileCopyHelper(mContext);
        copier.copyToExternalStorage(resid, out);
    }

    private int getFileCount(Uri uri) {
        Cursor cursor = mResolver.query(uri, null, null, null, null);
        try {
            return cursor.getCount();
        } finally {
            cursor.close();
        }
    }

    private void assertStringColumn(Uri fileUri, String columnName, String expectedValue) {
        Cursor cursor = mResolver.query(fileUri, null, null, null, null);
        try {
            assertTrue(cursor.moveToNext());
            int index = cursor.getColumnIndexOrThrow(columnName);
            assertEquals(expectedValue, cursor.getString(index));
        } finally {
            cursor.close();
        }
    }
}
