// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.base;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.os.AsyncTask;
import android.os.Environment;

import org.chromium.base.annotations.CalledByNative;

import java.io.File;
import java.util.concurrent.ExecutionException;

/**
 * This class provides the path related methods for the native library.
 */
public abstract class PathUtils {
    private static final String THUMBNAIL_DIRECTORY = "textures";

    private static final int DATA_DIRECTORY = 0;
    private static final int DATABASE_DIRECTORY = 1;
    private static final int CACHE_DIRECTORY = 2;
    private static final int DOWNLOADS_DIRECTORY = 3;
    private static final int NUM_DIRECTORIES = 4;
    private static AsyncTask<String, Void, String[]> sDirPathFetchTask;

    private static File sThumbnailDirectory;

    // Prevent instantiation.
    private PathUtils() {}

    /**
     * Starts an asynchronous task to fetch the path of the directory where private data is to be
     * stored by the application.
     *
     * @param suffix The private data directory suffix.
     * @see Context#getDir(String, int)
     */
    public static void setPrivateDataDirectorySuffix(String suffix, Context context) {
        final Context appContext = context.getApplicationContext();
        sDirPathFetchTask = new AsyncTask<String, Void, String[]>() {
            @Override
            protected String[] doInBackground(String... dataDirectorySuffix) {
                String[] paths = new String[NUM_DIRECTORIES];
                paths[DATA_DIRECTORY] =
                        appContext.getDir(dataDirectorySuffix[0], Context.MODE_PRIVATE).getPath();
                paths[DATABASE_DIRECTORY] = appContext.getDatabasePath("foo").getParent();
                // TODO(wnwen): Find a way to avoid calling this function in renderer process.
                if (appContext.getCacheDir() != null) {
                    // These paths are only available in the browser process.
                    paths[CACHE_DIRECTORY] = appContext.getCacheDir().getPath();
                    paths[DOWNLOADS_DIRECTORY] = Environment.getExternalStoragePublicDirectory(
                            Environment.DIRECTORY_DOWNLOADS).getPath();
                }
                return paths;
            }
        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, suffix);
    }

    /**
     * @param index The index of the cached directory path.
     * @return The directory path requested, or null if not available.
     */
    private static String getDirectoryPath(int index) {
        try {
            return sDirPathFetchTask.get()[index];
        } catch (InterruptedException e) {
        } catch (ExecutionException e) {
        }
        return null;
    }

    /**
     * @return the private directory that is used to store application data.
     */
    @CalledByNative
    public static String getDataDirectory(Context appContext) {
        assert sDirPathFetchTask != null : "setDataDirectorySuffix must be called first.";
        return getDirectoryPath(DATA_DIRECTORY);
    }

    /**
     * @return the private directory that is used to store application database.
     */
    @CalledByNative
    public static String getDatabaseDirectory(Context appContext) {
        assert sDirPathFetchTask != null : "setDataDirectorySuffix must be called first.";
        return getDirectoryPath(DATABASE_DIRECTORY);
    }

    /**
     * @return the cache directory.
     */
    @SuppressWarnings("unused")
    @CalledByNative
    public static String getCacheDirectory(Context appContext) {
        assert sDirPathFetchTask != null : "setDataDirectorySuffix must be called first.";
        return getDirectoryPath(CACHE_DIRECTORY);
    }

    public static File getThumbnailCacheDirectory(Context appContext) {
        if (sThumbnailDirectory == null) {
            sThumbnailDirectory = appContext.getDir(THUMBNAIL_DIRECTORY, Context.MODE_PRIVATE);
        }
        return sThumbnailDirectory;
    }

    @CalledByNative
    public static String getThumbnailCacheDirectoryPath(Context appContext) {
        return getThumbnailCacheDirectory(appContext).getAbsolutePath();
    }

    /**
     * @return the public downloads directory.
     */
    @SuppressWarnings("unused")
    @CalledByNative
    private static String getDownloadsDirectory(Context appContext) {
        assert sDirPathFetchTask != null : "setDataDirectorySuffix must be called first.";
        return getDirectoryPath(DOWNLOADS_DIRECTORY);
    }

    /**
     * @return the path to native libraries.
     */
    @SuppressWarnings("unused")
    @CalledByNative
    private static String getNativeLibraryDirectory(Context appContext) {
        ApplicationInfo ai = appContext.getApplicationInfo();
        if ((ai.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0
                || (ai.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
            return ai.nativeLibraryDir;
        }

        return "/system/lib/";
    }

    /**
     * @return the external storage directory.
     */
    @SuppressWarnings("unused")
    @CalledByNative
    public static String getExternalStorageDirectory() {
        return Environment.getExternalStorageDirectory().getAbsolutePath();
    }
}

@@ -784,62 +784,8 @@
  2;%0A
-    private static final int DOWNLOADS_DIRECTORY = 3;%0A
     
@@ -831,9 +831,9 @@
 S = 
-4
+3
 ;%0A  
@@ -2051,302 +2051,56 @@
     
-// These paths are only available in the browser process.%0A                    paths%5BCACHE_DIRECTORY%5D = appContext.getCacheDir().getPath();%0A                    paths%5BDOWNLOADS_DIRECTORY%5D = Environment.getExternalStoragePublicDirectory(%0A                            Environment.DIRECTORY_DOWNLOADS
+paths%5BCACHE_DIRECTORY%5D = appContext.getCacheDir(
 ).ge
@@ -4252,142 +4252,119 @@
     
-assert sDirPathFetchTask != null : %22setDataDirectorySuffix must be called first.%22;%0A        return getDirectoryPath(DOWNLOADS_DIRECTORY
+return Environment.getExternalStoragePublicDirectory(%0A                Environment.DIRECTORY_DOWNLOADS).getPath(
 );%0A 

Revert of Pre-cache downloads directory path in PathUtils. (patchset #1 id:1 of https://codereview.chromium.org/1281273003/ )