/*
 * 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 com.android.cts.externalstorageapp;

import android.content.Context;
import android.os.Environment;
import android.test.AndroidTestCase;
import android.util.Log;

import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * Tests common functionality that should be supported regardless of external
 * storage status.
 */
public class CommonExternalStorageTest extends AndroidTestCase {
    public static final String TAG = "CommonExternalStorageTest";

    public static final String PACKAGE_NONE = "com.android.cts.externalstorageapp";
    public static final String PACKAGE_READ = "com.android.cts.readexternalstorageapp";
    public static final String PACKAGE_WRITE = "com.android.cts.writeexternalstorageapp";

    /**
     * Dump helpful debugging details.
     */
    public void testDumpDebug() throws Exception {
        logCommand("/system/bin/id");
        logCommand("/system/bin/cat", "/proc/self/mountinfo");
    }

    /**
     * Primary storage must always be mounted.
     */
    public void testExternalStorageMounted() {
        assertEquals(Environment.MEDIA_MOUNTED, Environment.getExternalStorageState());
    }

    /**
     * Verify that single path is always first item in multiple.
     */
    public void testMultipleCacheDirs() throws Exception {
        final File single = getContext().getExternalCacheDir();
        assertNotNull("Primary storage must always be available", single);
        final File firstMultiple = getContext().getExternalCacheDirs()[0];
        assertEquals(single, firstMultiple);
    }

    /**
     * Verify that single path is always first item in multiple.
     */
    public void testMultipleFilesDirs() throws Exception {
        final File single = getContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        assertNotNull("Primary storage must always be available", single);
        final File firstMultiple = getContext()
                .getExternalFilesDirs(Environment.DIRECTORY_PICTURES)[0];
        assertEquals(single, firstMultiple);
    }

    /**
     * Verify that single path is always first item in multiple.
     */
    public void testMultipleObbDirs() throws Exception {
        final File single = getContext().getObbDir();
        assertNotNull("Primary storage must always be available", single);
        final File firstMultiple = getContext().getObbDirs()[0];
        assertEquals(single, firstMultiple);
    }

    /**
     * Verify we can write to our own package dirs.
     */
    public void testAllPackageDirsWritable() throws Exception {
        final List<File> paths = getAllPackageSpecificPaths(getContext());
        for (File path : paths) {
            assertNotNull("Valid media must be inserted during CTS", path);
            assertEquals("Valid media must be inserted during CTS", Environment.MEDIA_MOUNTED,
                    Environment.getStorageState(path));

            assertDirReadWriteAccess(path);

            final File directChild = new File(path, "directChild");
            final File subdir = new File(path, "subdir");
            final File subdirChild = new File(path, "subdirChild");

            writeInt(directChild, 32);
            subdir.mkdirs();
            assertDirReadWriteAccess(subdir);
            writeInt(subdirChild, 64);

            assertEquals(32, readInt(directChild));
            assertEquals(64, readInt(subdirChild));
        }

        for (File path : paths) {
            deleteContents(path);
        }
    }

    /**
     * Return a set of several package-specific external storage paths.
     */
    public static List<File> getAllPackageSpecificPaths(Context context) {
        final List<File> paths = new ArrayList<File>();
        Collections.addAll(paths, context.getExternalCacheDirs());
        Collections.addAll(paths, context.getExternalFilesDirs(null));
        Collections.addAll(paths, context.getExternalFilesDirs(Environment.DIRECTORY_PICTURES));
        Collections.addAll(paths, context.getObbDirs());
        return paths;
    }

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

    public static List<File> getPrimaryPackageSpecificPaths(Context context) {
        final List<File> paths = new ArrayList<File>();
        Collections.addAll(paths, context.getExternalCacheDir());
        Collections.addAll(paths, context.getExternalFilesDir(null));
        Collections.addAll(paths, context.getExternalFilesDir(Environment.DIRECTORY_PICTURES));
        Collections.addAll(paths, context.getObbDir());
        return paths;
    }

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

    public static File buildGiftForPackage(Context context, String packageName) {
        final File myCache = context.getExternalCacheDir();
        return new File(myCache.getAbsolutePath().replace(context.getPackageName(), packageName),
                packageName + ".gift");
    }

    public static File buildProbeFile(File dir) {
        return new File(dir, ".probe_" + System.nanoTime());
    }

    public static void assertDirReadOnlyAccess(File path) {
        Log.d(TAG, "Asserting read-only access to " + path);

        assertTrue("exists", path.exists());
        assertTrue("read", path.canRead());
        assertTrue("execute", path.canExecute());
        assertNotNull("list", path.list());

        try {
            final File probe = buildProbeFile(path);
            probe.createNewFile();
            probe.delete();
            fail("able to create probe!");
        } catch (IOException e) {
            // expected
        }
    }

    public static void assertDirReadWriteAccess(File path) {
        Log.d(TAG, "Asserting read/write access to " + path);

        assertTrue("exists", path.exists());
        assertTrue("read", path.canRead());
        assertTrue("execute", path.canExecute());
        assertNotNull("list", path.list());

        try {
            final File probe = buildProbeFile(path);
            probe.createNewFile();
            probe.delete();
        } catch (IOException e) {
            fail("failed to create probe!");
        }
    }

    public static void assertDirNoAccess(File path) {
        Log.d(TAG, "Asserting no access to " + path);

        assertFalse("read", path.canRead());
        assertNull("list", path.list());

        try {
            final File probe = buildProbeFile(path);
            probe.createNewFile();
            probe.delete();
            fail("able to create probe!");
        } catch (IOException e) {
            // expected
        }
    }

    public static void assertDirNoWriteAccess(File path) {
        Log.d(TAG, "Asserting no write access to " + path);

        try {
            final File probe = buildProbeFile(path);
            probe.createNewFile();
            probe.delete();
            fail("able to create probe!");
        } catch (IOException e) {
            // expected
        }
    }

    public static void assertFileReadOnlyAccess(File path) {
        try {
            new FileInputStream(path).close();
        } catch (IOException e) {
            fail("failed to read!");
        }

        try {
            new FileOutputStream(path, true).close();
            fail("able to write!");
        } catch (IOException e) {
            // expected
        }
    }

    public static void assertFileReadWriteAccess(File path) {
        try {
            new FileInputStream(path).close();
        } catch (IOException e) {
            fail("failed to read!");
        }

        try {
            new FileOutputStream(path, true).close();
        } catch (IOException e) {
            fail("failed to write!");
        }
    }

    public static void assertFileNoAccess(File path) {
        try {
            new FileInputStream(path).close();
            fail("able to read!");
        } catch (IOException e) {
            // expected
        }

        try {
            new FileOutputStream(path, true).close();
            fail("able to write!");
        } catch (IOException e) {
            // expected
        }
    }

    private static boolean isWhiteList(File file) {
        final String[] whiteLists = {
                "autorun.inf", ".android_secure", "android_secure"
        };
        if (file.getParentFile().getAbsolutePath().equals(
                Environment.getExternalStorageDirectory().getAbsolutePath())) {
            for (String whiteList : whiteLists) {
                if (file.getName().equalsIgnoreCase(whiteList)) {
                    return true;
                }
            }
        }
        return false;
    }

    private static File[] removeWhiteList(File[] files) {
        List<File> fileList = new ArrayList<File>();
        if (files == null) {
            return null;
        }

        for (File file : files) {
            if (!isWhiteList(file)) {
                fileList.add(file);
            }
        }
        return fileList.toArray(new File[fileList.size()]);
    }

    public static void deleteContents(File dir) throws IOException {
        File[] files = dir.listFiles();
        files = removeWhiteList(files);
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    deleteContents(file);
                }
                assertTrue(file.delete());
            }

            File[] dirs = removeWhiteList(dir.listFiles());
            assertEquals(0, dirs.length);
        }
    }

    public static void writeInt(File file, int value) throws IOException {
        final DataOutputStream os = new DataOutputStream(new FileOutputStream(file));
        try {
            os.writeInt(value);
        } finally {
            os.close();
        }
    }

    public static int readInt(File file) throws IOException {
        final DataInputStream is = new DataInputStream(new FileInputStream(file));
        try {
            return is.readInt();
        } finally {
            is.close();
        }
    }

    private static void logCommand(String... cmd) throws Exception {
        final Process proc = new ProcessBuilder(cmd).redirectErrorStream(true).start();

        final ByteArrayOutputStream buf = new ByteArrayOutputStream();
        copy(proc.getInputStream(), buf);
        final int res = proc.waitFor();

        Log.d(TAG, Arrays.toString(cmd) + " result " + res + ":");
        Log.d(TAG, buf.toString());
    }

    /** Shamelessly lifted from libcore.io.Streams */
    public static int copy(InputStream in, OutputStream out) throws IOException {
        int total = 0;
        byte[] buffer = new byte[8192];
        int c;
        while ((c = in.read(buffer)) != -1) {
            total += c;
            out.write(buffer, 0, c);
        }
        return total;
    }
}
