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