/*
       Licensed to the Apache Software Foundation (ASF) under one
       or more contributor license agreements.  See the NOTICE file
       distributed with this work for additional information
       regarding copyright ownership.  The ASF licenses this file
       to you 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 org.apache.cordova.file;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.util.Base64;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.LOG;
import org.apache.cordova.PermissionHelper;
import org.apache.cordova.PluginResult;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.security.Permission;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

/**
 * This class provides file and directory services to JavaScript.
 */
public class FileUtils extends CordovaPlugin {
    private static final String LOG_TAG = "FileUtils";

    public static int NOT_FOUND_ERR = 1;
    public static int SECURITY_ERR = 2;
    public static int ABORT_ERR = 3;

    public static int NOT_READABLE_ERR = 4;
    public static int ENCODING_ERR = 5;
    public static int NO_MODIFICATION_ALLOWED_ERR = 6;
    public static int INVALID_STATE_ERR = 7;
    public static int SYNTAX_ERR = 8;
    public static int INVALID_MODIFICATION_ERR = 9;
    public static int QUOTA_EXCEEDED_ERR = 10;
    public static int TYPE_MISMATCH_ERR = 11;
    public static int PATH_EXISTS_ERR = 12;

    /*
     * Permission callback codes
     */

    public static final int ACTION_GET_FILE = 0;
    public static final int ACTION_WRITE = 1;
    public static final int ACTION_GET_DIRECTORY = 2;

    public static final int WRITE = 3;
    public static final int READ = 4;

    public static int UNKNOWN_ERR = 1000;

    private boolean configured = false;

    private PendingRequests pendingRequests;



    /*
     * We need both read and write when accessing the storage, I think.
     */

    private String [] permissions = {
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE };

    // This field exists only to support getEntry, below, which has been deprecated
    private static FileUtils filePlugin;

    private interface FileOp {
        void run(JSONArray args) throws Exception;
    }

    private ArrayList<Filesystem> filesystems;

    public void registerFilesystem(Filesystem fs) {
    	if (fs != null && filesystemForName(fs.name)== null) {
    		this.filesystems.add(fs);
    	}
    }

    private Filesystem filesystemForName(String name) {
    	for (Filesystem fs:filesystems) {
    		if (fs != null && fs.name != null && fs.name.equals(name)) {
    			return fs;
    		}
    	}
    	return null;
    }

    protected String[] getExtraFileSystemsPreference(Activity activity) {
        String fileSystemsStr = preferences.getString("androidextrafilesystems", "files,files-external,documents,sdcard,cache,cache-external,assets,root");
        return fileSystemsStr.split(",");
    }

    protected void registerExtraFileSystems(String[] filesystems, HashMap<String, String> availableFileSystems) {
        HashSet<String> installedFileSystems = new HashSet<String>();

        /* Register filesystems in order */
        for (String fsName : filesystems) {
            if (!installedFileSystems.contains(fsName)) {
                String fsRoot = availableFileSystems.get(fsName);
                if (fsRoot != null) {
                    File newRoot = new File(fsRoot);
                    if (newRoot.mkdirs() || newRoot.isDirectory()) {
                        registerFilesystem(new LocalFilesystem(fsName, webView.getContext(), webView.getResourceApi(), newRoot));
                        installedFileSystems.add(fsName);
                    } else {
                       LOG.d(LOG_TAG, "Unable to create root dir for filesystem \"" + fsName + "\", skipping");
                    }
                } else {
                    LOG.d(LOG_TAG, "Unrecognized extra filesystem identifier: " + fsName);
                }
            }
        }
    }

    protected HashMap<String, String> getAvailableFileSystems(Activity activity) {
        Context context = activity.getApplicationContext();
        HashMap<String, String> availableFileSystems = new HashMap<String,String>();

        availableFileSystems.put("files", context.getFilesDir().getAbsolutePath());
        availableFileSystems.put("documents", new File(context.getFilesDir(), "Documents").getAbsolutePath());
        availableFileSystems.put("cache", context.getCacheDir().getAbsolutePath());
        availableFileSystems.put("root", "/");
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
          try {
            availableFileSystems.put("files-external", context.getExternalFilesDir(null).getAbsolutePath());
            availableFileSystems.put("sdcard", Environment.getExternalStorageDirectory().getAbsolutePath());
            availableFileSystems.put("cache-external", context.getExternalCacheDir().getAbsolutePath());
          }
          catch(NullPointerException e) {
              LOG.d(LOG_TAG, "External storage unavailable, check to see if USB Mass Storage Mode is on");
          }
        }

        return availableFileSystems;
    }

    @Override
    public void initialize(CordovaInterface cordova, CordovaWebView webView) {
    	super.initialize(cordova, webView);
    	this.filesystems = new ArrayList<Filesystem>();
        this.pendingRequests = new PendingRequests();

    	String tempRoot = null;
    	String persistentRoot = null;

    	Activity activity = cordova.getActivity();
    	String packageName = activity.getPackageName();

        String location = preferences.getString("androidpersistentfilelocation", "internal");

    	tempRoot = activity.getCacheDir().getAbsolutePath();
    	if ("internal".equalsIgnoreCase(location)) {
    		persistentRoot = activity.getFilesDir().getAbsolutePath() + "/files/";
    		this.configured = true;
    	} else if ("compatibility".equalsIgnoreCase(location)) {
    		/*
    		 *  Fall-back to compatibility mode -- this is the logic implemented in
    		 *  earlier versions of this plugin, and should be maintained here so
    		 *  that apps which were originally deployed with older versions of the
    		 *  plugin can continue to provide access to files stored under those
    		 *  versions.
    		 */
    		if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
    			persistentRoot = Environment.getExternalStorageDirectory().getAbsolutePath();
    			tempRoot = Environment.getExternalStorageDirectory().getAbsolutePath() +
    					"/Android/data/" + packageName + "/cache/";
    		} else {
    			persistentRoot = "/data/data/" + packageName;
    		}
    		this.configured = true;
    	}

    	if (this.configured) {
			// Create the directories if they don't exist.
			File tmpRootFile = new File(tempRoot);
            File persistentRootFile = new File(persistentRoot);
            tmpRootFile.mkdirs();
            persistentRootFile.mkdirs();

    		// Register initial filesystems
    		// Note: The temporary and persistent filesystems need to be the first two
    		// registered, so that they will match window.TEMPORARY and window.PERSISTENT,
    		// per spec.
    		this.registerFilesystem(new LocalFilesystem("temporary", webView.getContext(), webView.getResourceApi(), tmpRootFile));
    		this.registerFilesystem(new LocalFilesystem("persistent", webView.getContext(), webView.getResourceApi(), persistentRootFile));
    		this.registerFilesystem(new ContentFilesystem(webView.getContext(), webView.getResourceApi()));
            this.registerFilesystem(new AssetFilesystem(webView.getContext().getAssets(), webView.getResourceApi()));

            registerExtraFileSystems(getExtraFileSystemsPreference(activity), getAvailableFileSystems(activity));

    		// Initialize static plugin reference for deprecated getEntry method
    		if (filePlugin == null) {
    			FileUtils.filePlugin = this;
    		}
    	} else {
    		LOG.e(LOG_TAG, "File plugin configuration error: Please set AndroidPersistentFileLocation in config.xml to one of \"internal\" (for new applications) or \"compatibility\" (for compatibility with previous versions)");
    		activity.finish();
    	}
    }

    public static FileUtils getFilePlugin() {
		return filePlugin;
	}

	private Filesystem filesystemForURL(LocalFilesystemURL localURL) {
    	if (localURL == null) return null;
    	return filesystemForName(localURL.fsName);
    }

    @Override
    public Uri remapUri(Uri uri) {
        // Remap only cdvfile: URLs (not content:).
        if (!LocalFilesystemURL.FILESYSTEM_PROTOCOL.equals(uri.getScheme())) {
            return null;
        }
        try {
        	LocalFilesystemURL inputURL = LocalFilesystemURL.parse(uri);
        	Filesystem fs = this.filesystemForURL(inputURL);
        	if (fs == null) {
        		return null;
        	}
        	String path = fs.filesystemPathForURL(inputURL);
        	if (path != null) {
        		return Uri.parse("file://" + fs.filesystemPathForURL(inputURL));
        	}
        	return null;
        } catch (IllegalArgumentException e) {
        	return null;
        }
    }

    public boolean execute(String action, final String rawArgs, final CallbackContext callbackContext) {
        if (!configured) {
            callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, "File plugin is not configured. Please see the README.md file for details on how to update config.xml"));
            return true;
        }
        if (action.equals("testSaveLocationExists")) {
            threadhelper(new FileOp() {
                public void run(JSONArray args) {
                    boolean b = DirectoryManager.testSaveLocationExists();
                    callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, b));
                }
            }, rawArgs, callbackContext);
        }
        else if (action.equals("getFreeDiskSpace")) {
            threadhelper( new FileOp( ){
                public void run(JSONArray args) {
                    // The getFreeDiskSpace plugin API is not documented, but some apps call it anyway via exec().
                    // For compatibility it always returns free space in the primary external storage, and
                    // does NOT fallback to internal store if external storage is unavailable.
                    long l = DirectoryManager.getFreeExternalStorageSpace();
                    callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, l));
                }
            }, rawArgs, callbackContext);
        }
        else if (action.equals("testFileExists")) {
            threadhelper( new FileOp( ){
                public void run(JSONArray args) throws JSONException {
                    String fname=args.getString(0);
                    boolean b = DirectoryManager.testFileExists(fname);
                    callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, b));
                }
            }, rawArgs, callbackContext);
        }
        else if (action.equals("testDirectoryExists")) {
            threadhelper( new FileOp( ){
                public void run(JSONArray args) throws JSONException {
                    String fname=args.getString(0);
                    boolean b = DirectoryManager.testFileExists(fname);
                    callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, b));
                }
            }, rawArgs, callbackContext);
        }
        else if (action.equals("readAsText")) {
            threadhelper( new FileOp( ){
                public void run(JSONArray args) throws JSONException, MalformedURLException {
                    String encoding = args.getString(1);
                    int start = args.getInt(2);
                    int end = args.getInt(3);
                    String fname=args.getString(0);
                    readFileAs(fname, start, end, callbackContext, encoding, PluginResult.MESSAGE_TYPE_STRING);
                }
            }, rawArgs, callbackContext);
        }
        else if (action.equals("readAsDataURL")) {
            threadhelper( new FileOp( ){
                public void run(JSONArray args) throws JSONException, MalformedURLException  {
                    int start = args.getInt(1);
                    int end = args.getInt(2);
                    String fname=args.getString(0);
                    readFileAs(fname, start, end, callbackContext, null, -1);
                }
            }, rawArgs, callbackContext);
        }
        else if (action.equals("readAsArrayBuffer")) {
            threadhelper( new FileOp( ){
                public void run(JSONArray args) throws JSONException, MalformedURLException  {
                    int start = args.getInt(1);
                    int end = args.getInt(2);
                    String fname=args.getString(0);
                    readFileAs(fname, start, end, callbackContext, null, PluginResult.MESSAGE_TYPE_ARRAYBUFFER);
                }
            }, rawArgs, callbackContext);
        }
        else if (action.equals("readAsBinaryString")) {
            threadhelper( new FileOp( ){
                public void run(JSONArray args) throws JSONException, MalformedURLException  {
                    int start = args.getInt(1);
                    int end = args.getInt(2);
                    String fname=args.getString(0);
                    readFileAs(fname, start, end, callbackContext, null, PluginResult.MESSAGE_TYPE_BINARYSTRING);
                }
            }, rawArgs, callbackContext);
        }
        else if (action.equals("write")) {
            threadhelper( new FileOp( ){
                public void run(JSONArray args) throws JSONException, FileNotFoundException, IOException, NoModificationAllowedException {
                    String fname=args.getString(0);
                    String nativeURL = resolveLocalFileSystemURI(fname).getString("nativeURL");
                    String data=args.getString(1);
                    int offset=args.getInt(2);
                    Boolean isBinary=args.getBoolean(3);

                    if(needPermission(nativeURL, WRITE)) {
                        getWritePermission(rawArgs, ACTION_WRITE, callbackContext);
                    }
                    else {
                        long fileSize = write(fname, data, offset, isBinary);
                        callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, fileSize));
                    }

                }
            }, rawArgs, callbackContext);
        }
        else if (action.equals("truncate")) {
            threadhelper( new FileOp( ){
                public void run(JSONArray args) throws JSONException, FileNotFoundException, IOException, NoModificationAllowedException {
                    String fname=args.getString(0);
                    int offset=args.getInt(1);
                    long fileSize = truncateFile(fname, offset);
                    callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, fileSize));
                }
            }, rawArgs, callbackContext);
        }
        else if (action.equals("requestAllFileSystems")) {
            threadhelper( new FileOp( ){
                public void run(JSONArray args) throws IOException, JSONException {
                    callbackContext.success(requestAllFileSystems());
                }
            }, rawArgs, callbackContext);
        } else if (action.equals("requestAllPaths")) {
            cordova.getThreadPool().execute(
                    new Runnable() {
                        public void run() {
                        	try {
					callbackContext.success(requestAllPaths());
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
                        }
                    }
            );
        } else if (action.equals("requestFileSystem")) {
            threadhelper( new FileOp( ){
                public void run(JSONArray args) throws JSONException {
                    int fstype = args.getInt(0);
                    long requiredSize = args.optLong(1);
                    requestFileSystem(fstype, requiredSize, callbackContext);
                }
            }, rawArgs, callbackContext);
        }
        else if (action.equals("resolveLocalFileSystemURI")) {
            threadhelper( new FileOp( ){
                public void run(JSONArray args) throws IOException, JSONException {
                    String fname=args.getString(0);
                    JSONObject obj = resolveLocalFileSystemURI(fname);
                    callbackContext.success(obj);
                }
            }, rawArgs, callbackContext);
        }
        else if (action.equals("getFileMetadata")) {
            threadhelper( new FileOp( ){
                public void run(JSONArray args) throws FileNotFoundException, JSONException, MalformedURLException {
                    String fname=args.getString(0);
                    JSONObject obj = getFileMetadata(fname);
                    callbackContext.success(obj);
                }
            }, rawArgs, callbackContext);
        }
        else if (action.equals("getParent")) {
            threadhelper( new FileOp( ){
                public void run(JSONArray args) throws JSONException, IOException {
                    String fname=args.getString(0);
                    JSONObject obj = getParent(fname);
                    callbackContext.success(obj);
                }
            }, rawArgs, callbackContext);
        }
        else if (action.equals("getDirectory")) {
            threadhelper( new FileOp( ){
                public void run(JSONArray args) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
                    String dirname = args.getString(0);
                    String path = args.getString(1);
                    String nativeURL = resolveLocalFileSystemURI(dirname).getString("nativeURL");
                    boolean containsCreate = (args.isNull(2)) ? false : args.getJSONObject(2).optBoolean("create", false);

                    if(containsCreate && needPermission(nativeURL, WRITE)) {
                        getWritePermission(rawArgs, ACTION_GET_DIRECTORY, callbackContext);
                    }
                    else if(!containsCreate && needPermission(nativeURL, READ)) {
                        getReadPermission(rawArgs, ACTION_GET_DIRECTORY, callbackContext);
                    }
                    else {
                        JSONObject obj = getFile(dirname, path, args.optJSONObject(2), true);
                        callbackContext.success(obj);
                    }
                }
            }, rawArgs, callbackContext);
        }
        else if (action.equals("getFile")) {
            threadhelper( new FileOp( ){
                public void run(JSONArray args) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
                    String dirname = args.getString(0);
                    String path = args.getString(1);
                    String nativeURL = resolveLocalFileSystemURI(dirname).getString("nativeURL");
                    boolean containsCreate = (args.isNull(2)) ? false : args.getJSONObject(2).optBoolean("create", false);

                    if(containsCreate && needPermission(nativeURL, WRITE)) {
                        getWritePermission(rawArgs, ACTION_GET_FILE, callbackContext);
                    }
                    else if(!containsCreate && needPermission(nativeURL, READ)) {
                        getReadPermission(rawArgs, ACTION_GET_FILE, callbackContext);
                    }
                    else {
                        JSONObject obj = getFile(dirname, path, args.optJSONObject(2), false);
                        callbackContext.success(obj);
                    }
                }
            }, rawArgs, callbackContext);
        }
        else if (action.equals("remove")) {
            threadhelper( new FileOp( ){
                public void run(JSONArray args) throws JSONException, NoModificationAllowedException, InvalidModificationException, MalformedURLException {
                    String fname=args.getString(0);
                    boolean success = remove(fname);
                    if (success) {
                        callbackContext.success();
                    } else {
                        callbackContext.error(FileUtils.NO_MODIFICATION_ALLOWED_ERR);
                    }
                }
            }, rawArgs, callbackContext);
        }
        else if (action.equals("removeRecursively")) {
            threadhelper( new FileOp( ){
                public void run(JSONArray args) throws JSONException, FileExistsException, MalformedURLException, NoModificationAllowedException {
                    String fname=args.getString(0);
                    boolean success = removeRecursively(fname);
                    if (success) {
                        callbackContext.success();
                    } else {
                        callbackContext.error(FileUtils.NO_MODIFICATION_ALLOWED_ERR);
                    }
                }
            }, rawArgs, callbackContext);
        }
        else if (action.equals("moveTo")) {
            threadhelper( new FileOp( ){
                public void run(JSONArray args) throws JSONException, NoModificationAllowedException, IOException, InvalidModificationException, EncodingException, FileExistsException {
                    String fname=args.getString(0);
                    String newParent=args.getString(1);
                    String newName=args.getString(2);
                    JSONObject entry = transferTo(fname, newParent, newName, true);
                    callbackContext.success(entry);
                }
            }, rawArgs, callbackContext);
        }
        else if (action.equals("copyTo")) {
            threadhelper( new FileOp( ){
                public void run(JSONArray args) throws JSONException, NoModificationAllowedException, IOException, InvalidModificationException, EncodingException, FileExistsException {
                    String fname=args.getString(0);
                    String newParent=args.getString(1);
                    String newName=args.getString(2);
                    JSONObject entry = transferTo(fname, newParent, newName, false);
                    callbackContext.success(entry);
                }
            }, rawArgs, callbackContext);
        }
        else if (action.equals("readEntries")) {
            threadhelper( new FileOp( ){
                public void run(JSONArray args) throws FileNotFoundException, JSONException, MalformedURLException {
                    String fname=args.getString(0);
                    JSONArray entries = readEntries(fname);
                    callbackContext.success(entries);
                }
            }, rawArgs, callbackContext);
        }
        else if (action.equals("_getLocalFilesystemPath")) {
            // Internal method for testing: Get the on-disk location of a local filesystem url.
            // [Currently used for testing file-transfer]
            threadhelper( new FileOp( ){
                public void run(JSONArray args) throws FileNotFoundException, JSONException, MalformedURLException {
                    String localURLstr = args.getString(0);
                    String fname = filesystemPathForURL(localURLstr);
                    callbackContext.success(fname);
                }
            }, rawArgs, callbackContext);
        }
        else {
            return false;
        }
        return true;
    }

    private void getReadPermission(String rawArgs, int action, CallbackContext callbackContext) {
        int requestCode = pendingRequests.createRequest(rawArgs, action, callbackContext);
        PermissionHelper.requestPermission(this, requestCode, Manifest.permission.READ_EXTERNAL_STORAGE);
    }

    private void getWritePermission(String rawArgs, int action, CallbackContext callbackContext) {
        int requestCode = pendingRequests.createRequest(rawArgs, action, callbackContext);
        PermissionHelper.requestPermission(this, requestCode, Manifest.permission.WRITE_EXTERNAL_STORAGE);
    }

    private boolean hasReadPermission() {
        return PermissionHelper.hasPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
    }

    private boolean hasWritePermission() {
        return PermissionHelper.hasPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
    }

    private boolean needPermission(String nativeURL, int permissionType) throws JSONException {
        JSONObject j = requestAllPaths();
        ArrayList<String> allowedStorageDirectories = new ArrayList<String>();
        allowedStorageDirectories.add(j.getString("applicationDirectory"));
        allowedStorageDirectories.add(j.getString("applicationStorageDirectory"));
        if(j.has("externalApplicationStorageDirectory")) {
            allowedStorageDirectories.add(j.getString("externalApplicationStorageDirectory"));
        }

        if(permissionType == READ && hasReadPermission()) {
            return false;
        }
        else if(permissionType == WRITE && hasWritePermission()) {
            return false;
        }

        // Permission required if the native url lies outside the allowed storage directories
        for(String directory : allowedStorageDirectories) {
            if(nativeURL.startsWith(directory)) {
                return false;
            }
        }
        return true;
    }


    public LocalFilesystemURL resolveNativeUri(Uri nativeUri) {
        LocalFilesystemURL localURL = null;

        // Try all installed filesystems. Return the best matching URL
        // (determined by the shortest resulting URL)
        for (Filesystem fs : filesystems) {
            LocalFilesystemURL url = fs.toLocalUri(nativeUri);
            if (url != null) {
                // A shorter fullPath implies that the filesystem is a better
                // match for the local path than the previous best.
                if (localURL == null || (url.uri.toString().length() < localURL.toString().length())) {
                    localURL = url;
                }
            }
        }
        return localURL;
    }

    /*
     * These two native-only methods can be used by other plugins to translate between
     * device file system paths and URLs. By design, there is no direct JavaScript
     * interface to these methods.
     */

    public String filesystemPathForURL(String localURLstr) throws MalformedURLException {
        try {
            LocalFilesystemURL inputURL = LocalFilesystemURL.parse(localURLstr);
            Filesystem fs = this.filesystemForURL(inputURL);
            if (fs == null) {
                throw new MalformedURLException("No installed handlers for this URL");
            }
            return fs.filesystemPathForURL(inputURL);
        } catch (IllegalArgumentException e) {
            MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
            mue.initCause(e);
        	throw mue;
        }
    }

    public LocalFilesystemURL filesystemURLforLocalPath(String localPath) {
        LocalFilesystemURL localURL = null;
        int shortestFullPath = 0;

        // Try all installed filesystems. Return the best matching URL
        // (determined by the shortest resulting URL)
        for (Filesystem fs: filesystems) {
            LocalFilesystemURL url = fs.URLforFilesystemPath(localPath);
            if (url != null) {
                // A shorter fullPath implies that the filesystem is a better
                // match for the local path than the previous best.
                if (localURL == null || (url.path.length() < shortestFullPath)) {
                    localURL = url;
                    shortestFullPath = url.path.length();
                }
            }
        }
        return localURL;
    }


	/* helper to execute functions async and handle the result codes
     *
     */
    private void threadhelper(final FileOp f, final String rawArgs, final CallbackContext callbackContext){
        cordova.getThreadPool().execute(new Runnable() {
            public void run() {
                try {
                    JSONArray args = new JSONArray(rawArgs);
                    f.run(args);
                } catch ( Exception e) {
                    if( e instanceof EncodingException){
                        callbackContext.error(FileUtils.ENCODING_ERR);
                    } else if(e instanceof FileNotFoundException) {
                        callbackContext.error(FileUtils.NOT_FOUND_ERR);
                    } else if(e instanceof FileExistsException) {
                        callbackContext.error(FileUtils.PATH_EXISTS_ERR);
                    } else if(e instanceof NoModificationAllowedException ) {
                        callbackContext.error(FileUtils.NO_MODIFICATION_ALLOWED_ERR);
                    } else if(e instanceof InvalidModificationException ) {
                        callbackContext.error(FileUtils.INVALID_MODIFICATION_ERR);
                    } else if(e instanceof MalformedURLException ) {
                        callbackContext.error(FileUtils.ENCODING_ERR);
                    } else if(e instanceof IOException ) {
                        callbackContext.error(FileUtils.INVALID_MODIFICATION_ERR);
                    } else if(e instanceof EncodingException ) {
                        callbackContext.error(FileUtils.ENCODING_ERR);
                    } else if(e instanceof TypeMismatchException ) {
                        callbackContext.error(FileUtils.TYPE_MISMATCH_ERR);
                    } else if(e instanceof JSONException ) {
                        callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
                    } else if (e instanceof SecurityException) {
                        callbackContext.error(FileUtils.SECURITY_ERR);
                    } else {
                        e.printStackTrace();
                    	callbackContext.error(FileUtils.UNKNOWN_ERR);
                    }
                }
            }
        });
    }

    /**
     * Allows the user to look up the Entry for a file or directory referred to by a local URI.
     *
     * @param uriString of the file/directory to look up
     * @return a JSONObject representing a Entry from the filesystem
     * @throws MalformedURLException if the url is not valid
     * @throws FileNotFoundException if the file does not exist
     * @throws IOException if the user can't read the file
     * @throws JSONException
     */
    private JSONObject resolveLocalFileSystemURI(String uriString) throws IOException, JSONException {
        if (uriString == null) {
            throw new MalformedURLException("Unrecognized filesystem URL");
        }
        Uri uri = Uri.parse(uriString);
        boolean isNativeUri = false;

        LocalFilesystemURL inputURL = LocalFilesystemURL.parse(uri);
        if (inputURL == null) {
            /* Check for file://, content:// urls */
            inputURL = resolveNativeUri(uri);
            isNativeUri = true;
        }

        try {
            Filesystem fs = this.filesystemForURL(inputURL);
            if (fs == null) {
                throw new MalformedURLException("No installed handlers for this URL");
            }
            if (fs.exists(inputURL)) {
                if (!isNativeUri) {
                    // If not already resolved as native URI, resolve to a native URI and back to
                    // fix the terminating slash based on whether the entry is a directory or file.
                    inputURL = fs.toLocalUri(fs.toNativeUri(inputURL));
                }

                return fs.getEntryForLocalURL(inputURL);
            }
        } catch (IllegalArgumentException e) {
            MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
            mue.initCause(e);
        	throw mue;
        }
        throw new FileNotFoundException();
    }

    /**
     * Read the list of files from this directory.
     *
     * @return a JSONArray containing JSONObjects that represent Entry objects.
     * @throws FileNotFoundException if the directory is not found.
     * @throws JSONException
     * @throws MalformedURLException
     */
    private JSONArray readEntries(String baseURLstr) throws FileNotFoundException, JSONException, MalformedURLException {
        try {
        	LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
        	Filesystem fs = this.filesystemForURL(inputURL);
        	if (fs == null) {
        		throw new MalformedURLException("No installed handlers for this URL");
        	}
        	return fs.readEntriesAtLocalURL(inputURL);

        } catch (IllegalArgumentException e) {
            MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
            mue.initCause(e);
        	throw mue;
        }
    }

    /**
     * A setup method that handles the move/copy of files/directories
     *
     * @param newName for the file directory to be called, if null use existing file name
     * @param move if false do a copy, if true do a move
     * @return a Entry object
     * @throws NoModificationAllowedException
     * @throws IOException
     * @throws InvalidModificationException
     * @throws EncodingException
     * @throws JSONException
     * @throws FileExistsException
     */
    private JSONObject transferTo(String srcURLstr, String destURLstr, String newName, boolean move) throws JSONException, NoModificationAllowedException, IOException, InvalidModificationException, EncodingException, FileExistsException {
        if (srcURLstr == null || destURLstr == null) {
            // either no source or no destination provided
        	throw new FileNotFoundException();
        }

        LocalFilesystemURL srcURL = LocalFilesystemURL.parse(srcURLstr);
        LocalFilesystemURL destURL = LocalFilesystemURL.parse(destURLstr);

        Filesystem srcFs = this.filesystemForURL(srcURL);
        Filesystem destFs = this.filesystemForURL(destURL);

        // Check for invalid file name
        if (newName != null && newName.contains(":")) {
            throw new EncodingException("Bad file name");
        }

        return destFs.copyFileToURL(destURL, newName, srcFs, srcURL, move);
    }

    /**
     * Deletes a directory and all of its contents, if any. In the event of an error
     * [e.g. trying to delete a directory that contains a file that cannot be removed],
     * some of the contents of the directory may be deleted.
     * It is an error to attempt to delete the root directory of a filesystem.
     *
     * @return a boolean representing success of failure
     * @throws FileExistsException
     * @throws NoModificationAllowedException
     * @throws MalformedURLException
     */
    private boolean removeRecursively(String baseURLstr) throws FileExistsException, NoModificationAllowedException, MalformedURLException {
        try {
        	LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
        	// You can't delete the root directory.
        	if ("".equals(inputURL.path) || "/".equals(inputURL.path)) {
        		throw new NoModificationAllowedException("You can't delete the root directory");
        	}

        	Filesystem fs = this.filesystemForURL(inputURL);
        	if (fs == null) {
        		throw new MalformedURLException("No installed handlers for this URL");
        	}
        	return fs.recursiveRemoveFileAtLocalURL(inputURL);

        } catch (IllegalArgumentException e) {
            MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
            mue.initCause(e);
        	throw mue;
        }
    }


    /**
     * Deletes a file or directory. It is an error to attempt to delete a directory that is not empty.
     * It is an error to attempt to delete the root directory of a filesystem.
     *
     * @return a boolean representing success of failure
     * @throws NoModificationAllowedException
     * @throws InvalidModificationException
     * @throws MalformedURLException
     */
    private boolean remove(String baseURLstr) throws NoModificationAllowedException, InvalidModificationException, MalformedURLException {
        try {
        	LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
        	// You can't delete the root directory.
        	if ("".equals(inputURL.path) || "/".equals(inputURL.path)) {

        		throw new NoModificationAllowedException("You can't delete the root directory");
        	}

        	Filesystem fs = this.filesystemForURL(inputURL);
        	if (fs == null) {
        		throw new MalformedURLException("No installed handlers for this URL");
        	}
        	return fs.removeFileAtLocalURL(inputURL);

        } catch (IllegalArgumentException e) {
            MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
            mue.initCause(e);
        	throw mue;
        }
    }

    /**
     * Creates or looks up a file.
     *
     * @param baseURLstr base directory
     * @param path file/directory to lookup or create
     * @param options specify whether to create or not
     * @param directory if true look up directory, if false look up file
     * @return a Entry object
     * @throws FileExistsException
     * @throws IOException
     * @throws TypeMismatchException
     * @throws EncodingException
     * @throws JSONException
     */
    private JSONObject getFile(String baseURLstr, String path, JSONObject options, boolean directory) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
        try {
        	LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
        	Filesystem fs = this.filesystemForURL(inputURL);
        	if (fs == null) {
        		throw new MalformedURLException("No installed handlers for this URL");
        	}
        	return fs.getFileForLocalURL(inputURL, path, options, directory);

        } catch (IllegalArgumentException e) {
            MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
            mue.initCause(e);
        	throw mue;
        }

    }

    /**
     * Look up the parent DirectoryEntry containing this Entry.
     * If this Entry is the root of its filesystem, its parent is itself.
     */
    private JSONObject getParent(String baseURLstr) throws JSONException, IOException {
        try {
        	LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
        	Filesystem fs = this.filesystemForURL(inputURL);
        	if (fs == null) {
        		throw new MalformedURLException("No installed handlers for this URL");
        	}
        	return fs.getParentForLocalURL(inputURL);

        } catch (IllegalArgumentException e) {
            MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
            mue.initCause(e);
        	throw mue;
        }
    }

    /**
     * Returns a File that represents the current state of the file that this FileEntry represents.
     *
     * @return returns a JSONObject represent a W3C File object
     */
    private JSONObject getFileMetadata(String baseURLstr) throws FileNotFoundException, JSONException, MalformedURLException {
        try {
        	LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
        	Filesystem fs = this.filesystemForURL(inputURL);
        	if (fs == null) {
        		throw new MalformedURLException("No installed handlers for this URL");
        	}
        	return fs.getFileMetadataForLocalURL(inputURL);

        } catch (IllegalArgumentException e) {
            MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
            mue.initCause(e);
        	throw mue;
        }
    }

    /**
     * Requests a filesystem in which to store application data.
     *
     * @param type of file system requested
     * @param requiredSize required free space in the file system in bytes
     * @param callbackContext context for returning the result or error
     * @throws JSONException
     */
    private void requestFileSystem(int type, long requiredSize, final CallbackContext callbackContext) throws JSONException {
        Filesystem rootFs = null;
        try {
            rootFs = this.filesystems.get(type);
        } catch (ArrayIndexOutOfBoundsException e) {
            // Pass null through
        }
        if (rootFs == null) {
            callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, FileUtils.NOT_FOUND_ERR));
        } else {
            // If a nonzero required size was specified, check that the retrieved filesystem has enough free space.
            long availableSize = 0;
            if (requiredSize > 0) {
                availableSize = rootFs.getFreeSpaceInBytes();
            }

            if (availableSize < requiredSize) {
                callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, FileUtils.QUOTA_EXCEEDED_ERR));
            } else {
                JSONObject fs = new JSONObject();
                fs.put("name", rootFs.name);
                fs.put("root", rootFs.getRootEntry());
                callbackContext.success(fs);
            }
        }
    }

    /**
     * Requests a filesystem in which to store application data.
     *
     * @return a JSONObject representing the file system
     */
    private JSONArray requestAllFileSystems() throws IOException, JSONException {
        JSONArray ret = new JSONArray();
        for (Filesystem fs : filesystems) {
            ret.put(fs.getRootEntry());
        }
        return ret;
    }

    private static String toDirUrl(File f) {
        return Uri.fromFile(f).toString() + '/';
    }

    private JSONObject requestAllPaths() throws JSONException {
        Context context = cordova.getActivity();
        JSONObject ret = new JSONObject();
        ret.put("applicationDirectory", "file:///android_asset/");
        ret.put("applicationStorageDirectory", toDirUrl(context.getFilesDir().getParentFile()));
        ret.put("dataDirectory", toDirUrl(context.getFilesDir()));
        ret.put("cacheDirectory", toDirUrl(context.getCacheDir()));
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
          try {
            ret.put("externalApplicationStorageDirectory", toDirUrl(context.getExternalFilesDir(null).getParentFile()));
            ret.put("externalDataDirectory", toDirUrl(context.getExternalFilesDir(null)));
            ret.put("externalCacheDirectory", toDirUrl(context.getExternalCacheDir()));
            ret.put("externalRootDirectory", toDirUrl(Environment.getExternalStorageDirectory()));
          }
          catch(NullPointerException e) {
            /* If external storage is unavailable, context.getExternal* returns null */
              LOG.d(LOG_TAG, "Unable to access these paths, most liklely due to USB storage");
          }
        }
        return ret;
    }

   /**
     * Returns a JSON object representing the given File. Internal APIs should be modified
     * to use URLs instead of raw FS paths wherever possible, when interfacing with this plugin.
     *
     * @param file the File to convert
     * @return a JSON representation of the given File
     * @throws JSONException
     */
    public JSONObject getEntryForFile(File file) throws JSONException {
        JSONObject entry;

        for (Filesystem fs : filesystems) {
             entry = fs.makeEntryForFile(file);
             if (entry != null) {
                 return entry;
             }
        }
        return null;
    }

    /**
     * Returns a JSON object representing the given File. Deprecated, as this is only used by
     * FileTransfer, and because it is a static method that should really be an instance method,
     * since it depends on the actual filesystem roots in use. Internal APIs should be modified
     * to use URLs instead of raw FS paths wherever possible, when interfacing with this plugin.
     *
     * @param file the File to convert
     * @return a JSON representation of the given File
     * @throws JSONException
     */
    @Deprecated
    public static JSONObject getEntry(File file) throws JSONException {
 		if (getFilePlugin() != null) {
             return getFilePlugin().getEntryForFile(file);
		}
		return null;
    }

    /**
     * Read the contents of a file.
     * This is done in a background thread; the result is sent to the callback.
     *
     * @param start             Start position in the file.
     * @param end               End position to stop at (exclusive).
     * @param callbackContext   The context through which to send the result.
     * @param encoding          The encoding to return contents as.  Typical value is UTF-8. (see http://www.iana.org/assignments/character-sets)
     * @param resultType        The desired type of data to send to the callback.
     * @return                  Contents of file.
     */
    public void readFileAs(final String srcURLstr, final int start, final int end, final CallbackContext callbackContext, final String encoding, final int resultType) throws MalformedURLException {
        try {
        	LocalFilesystemURL inputURL = LocalFilesystemURL.parse(srcURLstr);
        	Filesystem fs = this.filesystemForURL(inputURL);
        	if (fs == null) {
        		throw new MalformedURLException("No installed handlers for this URL");
        	}

            fs.readFileAtURL(inputURL, start, end, new Filesystem.ReadFileCallback() {
                public void handleData(InputStream inputStream, String contentType) {
            		try {
                        ByteArrayOutputStream os = new ByteArrayOutputStream();
                        final int BUFFER_SIZE = 8192;
                        byte[] buffer = new byte[BUFFER_SIZE];

                        for (;;) {
                            int bytesRead = inputStream.read(buffer, 0, BUFFER_SIZE);

                            if (bytesRead <= 0) {
                                break;
                            }
                            os.write(buffer, 0, bytesRead);
                        }

            			PluginResult result;
            			switch (resultType) {
            			case PluginResult.MESSAGE_TYPE_STRING:
                            result = new PluginResult(PluginResult.Status.OK, os.toString(encoding));
            				break;
            			case PluginResult.MESSAGE_TYPE_ARRAYBUFFER:
                            result = new PluginResult(PluginResult.Status.OK, os.toByteArray());
            				break;
            			case PluginResult.MESSAGE_TYPE_BINARYSTRING:
                            result = new PluginResult(PluginResult.Status.OK, os.toByteArray(), true);
            				break;
            			default: // Base64.
                        byte[] base64 = Base64.encode(os.toByteArray(), Base64.NO_WRAP);
            			String s = "data:" + contentType + ";base64," + new String(base64, "US-ASCII");
            			result = new PluginResult(PluginResult.Status.OK, s);
            			}

            			callbackContext.sendPluginResult(result);
            		} catch (IOException e) {
            			LOG.d(LOG_TAG, e.getLocalizedMessage());
            			callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, NOT_READABLE_ERR));
                    }
            	}
            });


        } catch (IllegalArgumentException e) {
            MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
            mue.initCause(e);
        	throw mue;
        } catch (FileNotFoundException e) {
        	callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, NOT_FOUND_ERR));
        } catch (IOException e) {
        	LOG.d(LOG_TAG, e.getLocalizedMessage());
        	callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, NOT_READABLE_ERR));
        }
    }


    /**
     * Write contents of file.
     *
     * @param data				The contents of the file.
     * @param offset			The position to begin writing the file.
     * @param isBinary          True if the file contents are base64-encoded binary data
     */
    /**/
    public long write(String srcURLstr, String data, int offset, boolean isBinary) throws FileNotFoundException, IOException, NoModificationAllowedException {
        try {
        	LocalFilesystemURL inputURL = LocalFilesystemURL.parse(srcURLstr);
        	Filesystem fs = this.filesystemForURL(inputURL);
        	if (fs == null) {
        		throw new MalformedURLException("No installed handlers for this URL");
        	}

            long x = fs.writeToFileAtURL(inputURL, data, offset, isBinary); LOG.d("TEST",srcURLstr + ": "+x); return x;
        } catch (IllegalArgumentException e) {
            MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
            mue.initCause(e);
        	throw mue;
        }

    }

    /**
     * Truncate the file to size
     */
    private long truncateFile(String srcURLstr, long size) throws FileNotFoundException, IOException, NoModificationAllowedException {
        try {
        	LocalFilesystemURL inputURL = LocalFilesystemURL.parse(srcURLstr);
        	Filesystem fs = this.filesystemForURL(inputURL);
        	if (fs == null) {
        		throw new MalformedURLException("No installed handlers for this URL");
        	}

            return fs.truncateFileAtURL(inputURL, size);
        } catch (IllegalArgumentException e) {
            MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
            mue.initCause(e);
        	throw mue;
        }
    }


    /*
     * Handle the response
     */

    public void onRequestPermissionResult(int requestCode, String[] permissions,
                                          int[] grantResults) throws JSONException {

        final PendingRequests.Request req = pendingRequests.getAndRemove(requestCode);
        if (req != null) {
            for(int r:grantResults)
            {
                if(r == PackageManager.PERMISSION_DENIED)
                {
                    req.getCallbackContext().sendPluginResult(new PluginResult(PluginResult.Status.ERROR, SECURITY_ERR));
                    return;
                }
            }
            switch(req.getAction())
            {
                case ACTION_GET_FILE:
                    threadhelper( new FileOp( ){
                        public void run(JSONArray args) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
                            String dirname = args.getString(0);

                            String path = args.getString(1);
                            JSONObject obj = getFile(dirname, path, args.optJSONObject(2), false);
                            req.getCallbackContext().success(obj);
                        }
                    }, req.getRawArgs(), req.getCallbackContext());
                    break;
                case ACTION_GET_DIRECTORY:
                    threadhelper( new FileOp( ){
                        public void run(JSONArray args) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
                            String dirname = args.getString(0);

                            String path = args.getString(1);
                            JSONObject obj = getFile(dirname, path, args.optJSONObject(2), true);
                            req.getCallbackContext().success(obj);
                        }
                    }, req.getRawArgs(), req.getCallbackContext());
                    break;
                case ACTION_WRITE:
                    threadhelper( new FileOp( ){
                        public void run(JSONArray args) throws JSONException, FileNotFoundException, IOException, NoModificationAllowedException {
                            String fname=args.getString(0);
                            String data=args.getString(1);
                            int offset=args.getInt(2);
                            Boolean isBinary=args.getBoolean(3);
                            long fileSize = write(fname, data, offset, isBinary);
                            req.getCallbackContext().sendPluginResult(new PluginResult(PluginResult.Status.OK, fileSize));
                        }
                    }, req.getRawArgs(), req.getCallbackContext());
                    break;
            }
        } else {
           LOG.d(LOG_TAG, "Received permission callback for unknown request code");
        }
    }
}
