/*
 *
 * 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.
 *
 */

/* global IDBKeyRange */

var LocalFileSystem = require('./LocalFileSystem');
var FileSystem = require('./FileSystem');
var FileEntry = require('./FileEntry');
var FileError = require('./FileError');
var DirectoryEntry = require('./DirectoryEntry'); // eslint-disable-line no-undef
var File = require('./File');

/*
QUIRKS:
    Does not fail when removing non-empty directories
    Does not support metadata for directories
    Does not support requestAllFileSystems
    Does not support resolveLocalFileSystemURI
    Methods copyTo and moveTo do not support directories

    Heavily based on https://github.com/ebidel/idb.filesystem.js
 */

(function (exports, global) {
    var indexedDB = global.indexedDB || global.mozIndexedDB;
    if (!indexedDB) {
        throw 'Firefox OS File plugin: indexedDB not supported';
    }

    var fs_ = null;

    var idb_ = {};
    idb_.db = null;
    var FILE_STORE_ = 'entries';

    var DIR_SEPARATOR = '/';
    var DIR_OPEN_BOUND = String.fromCharCode(DIR_SEPARATOR.charCodeAt(0) + 1);

    var pathsPrefix = {
        // Read-only directory where the application is installed.
        applicationDirectory: location.origin + '/', // eslint-disable-line no-undef
        // Where to put app-specific data files.
        dataDirectory: 'file:///persistent/',
        // Cached files that should survive app restarts.
        // Apps should not rely on the OS to delete files in here.
        cacheDirectory: 'file:///temporary/'
    };

/** * Exported functionality ***/

    exports.requestFileSystem = function (successCallback, errorCallback, args) {
        var type = args[0];
        // var size = args[1];

        if (type !== LocalFileSystem.TEMPORARY && type !== LocalFileSystem.PERSISTENT) {
            if (errorCallback) {
                errorCallback(FileError.INVALID_MODIFICATION_ERR);
            }
            return;
        }

        var name = type === LocalFileSystem.TEMPORARY ? 'temporary' : 'persistent';
        var storageName = (location.protocol + location.host).replace(/:/g, '_'); // eslint-disable-line no-undef

        var root = new DirectoryEntry('', DIR_SEPARATOR);
        fs_ = new FileSystem(name, root);

        idb_.open(storageName, function () {
            successCallback(fs_);
        }, errorCallback);
    };

    require('./fileSystems').getFs = function (name, callback) {
        callback(new FileSystem(name, fs_.root));
    };

    // list a directory's contents (files and folders).
    exports.readEntries = function (successCallback, errorCallback, args) {
        var fullPath = args[0];

        if (!successCallback) {
            throw Error('Expected successCallback argument.');
        }

        var path = resolveToFullPath_(fullPath);

        idb_.getAllEntries(path.fullPath, path.storagePath, function (entries) {
            successCallback(entries);
        }, errorCallback);
    };

    exports.getFile = function (successCallback, errorCallback, args) {
        var fullPath = args[0];
        var path = args[1];
        var options = args[2] || {};

        // Create an absolute path if we were handed a relative one.
        path = resolveToFullPath_(fullPath, path);

        idb_.get(path.storagePath, function (fileEntry) {
            if (options.create === true && options.exclusive === true && fileEntry) {
                // If create and exclusive are both true, and the path already exists,
                // getFile must fail.

                if (errorCallback) {
                    errorCallback(FileError.PATH_EXISTS_ERR);
                }
            } else if (options.create === true && !fileEntry) {
                // If create is true, the path doesn't exist, and no other error occurs,
                // getFile must create it as a zero-length file and return a corresponding
                // FileEntry.
                var newFileEntry = new FileEntry(path.fileName, path.fullPath, new FileSystem(path.fsName, fs_.root));

                newFileEntry.file_ = new MyFile({
                    size: 0,
                    name: newFileEntry.name,
                    lastModifiedDate: new Date(),
                    storagePath: path.storagePath
                });

                idb_.put(newFileEntry, path.storagePath, successCallback, errorCallback);
            } else if (options.create === true && fileEntry) {
                if (fileEntry.isFile) {
                    // Overwrite file, delete then create new.
                    idb_['delete'](path.storagePath, function () {
                        var newFileEntry = new FileEntry(path.fileName, path.fullPath, new FileSystem(path.fsName, fs_.root));

                        newFileEntry.file_ = new MyFile({
                            size: 0,
                            name: newFileEntry.name,
                            lastModifiedDate: new Date(),
                            storagePath: path.storagePath
                        });

                        idb_.put(newFileEntry, path.storagePath, successCallback, errorCallback);
                    }, errorCallback);
                } else {
                    if (errorCallback) {
                        errorCallback(FileError.INVALID_MODIFICATION_ERR);
                    }
                }
            } else if ((!options.create || options.create === false) && !fileEntry) {
                // If create is not true and the path doesn't exist, getFile must fail.
                if (errorCallback) {
                    errorCallback(FileError.NOT_FOUND_ERR);
                }
            } else if ((!options.create || options.create === false) && fileEntry &&
                fileEntry.isDirectory) {
                // If create is not true and the path exists, but is a directory, getFile
                // must fail.
                if (errorCallback) {
                    errorCallback(FileError.INVALID_MODIFICATION_ERR);
                }
            } else {
                // Otherwise, if no other error occurs, getFile must return a FileEntry
                // corresponding to path.

                successCallback(fileEntryFromIdbEntry(fileEntry));
            }
        }, errorCallback);
    };

    exports.getFileMetadata = function (successCallback, errorCallback, args) {
        var fullPath = args[0];

        exports.getFile(function (fileEntry) {
            successCallback(new File(fileEntry.file_.name, fileEntry.fullPath, '', fileEntry.file_.lastModifiedDate,
                fileEntry.file_.size));
        }, errorCallback, [fullPath, null]);
    };

    exports.getMetadata = function (successCallback, errorCallback, args) {
        exports.getFile(function (fileEntry) {
            successCallback(
                {
                    modificationTime: fileEntry.file_.lastModifiedDate,
                    size: fileEntry.file_.lastModifiedDate
                });
        }, errorCallback, args);
    };

    exports.setMetadata = function (successCallback, errorCallback, args) {
        var fullPath = args[0];
        var metadataObject = args[1];

        exports.getFile(function (fileEntry) {
            fileEntry.file_.lastModifiedDate = metadataObject.modificationTime;
        }, errorCallback, [fullPath, null]);
    };

    exports.write = function (successCallback, errorCallback, args) {
        var fileName = args[0];
        var data = args[1];
        var position = args[2];
            // isBinary = args[3];

        if (!data) {
            if (errorCallback) {
                errorCallback(FileError.INVALID_MODIFICATION_ERR);
            }
            return;
        }

        exports.getFile(function (fileEntry) {
            var blob_ = fileEntry.file_.blob_;

            if (!blob_) {
                blob_ = new Blob([data], {type: data.type}); // eslint-disable-line no-undef
            } else {
                // Calc the head and tail fragments
                var head = blob_.slice(0, position);
                var tail = blob_.slice(position + data.byteLength);

                // Calc the padding
                var padding = position - head.size;
                if (padding < 0) {
                    padding = 0;
                }

                // Do the "write". In fact, a full overwrite of the Blob.
                blob_ = new Blob([head, new Uint8Array(padding), data, tail], // eslint-disable-line no-undef
                    {type: data.type});
            }

            // Set the blob we're writing on this file entry so we can recall it later.
            fileEntry.file_.blob_ = blob_;
            fileEntry.file_.lastModifiedDate = data.lastModifiedDate || null;
            fileEntry.file_.size = blob_.size;
            fileEntry.file_.name = blob_.name;
            fileEntry.file_.type = blob_.type;

            idb_.put(fileEntry, fileEntry.file_.storagePath, function () {
                successCallback(data.byteLength);
            }, errorCallback);
        }, errorCallback, [fileName, null]);
    };

    exports.readAsText = function (successCallback, errorCallback, args) {
        var fileName = args[0];
        var enc = args[1];
        var startPos = args[2];
        var endPos = args[3];

        readAs('text', fileName, enc, startPos, endPos, successCallback, errorCallback);
    };

    exports.readAsDataURL = function (successCallback, errorCallback, args) {
        var fileName = args[0];
        var startPos = args[1];
        var endPos = args[2];

        readAs('dataURL', fileName, null, startPos, endPos, successCallback, errorCallback);
    };

    exports.readAsBinaryString = function (successCallback, errorCallback, args) {
        var fileName = args[0];
        var startPos = args[1];
        var endPos = args[2];

        readAs('binaryString', fileName, null, startPos, endPos, successCallback, errorCallback);
    };

    exports.readAsArrayBuffer = function (successCallback, errorCallback, args) {
        var fileName = args[0];
        var startPos = args[1];
        var endPos = args[2];

        readAs('arrayBuffer', fileName, null, startPos, endPos, successCallback, errorCallback);
    };

    exports.removeRecursively = exports.remove = function (successCallback, errorCallback, args) {
        var fullPath = args[0];

        // TODO: This doesn't protect against directories that have content in it.
        // Should throw an error instead if the dirEntry is not empty.
        idb_['delete'](fullPath, function () {
            successCallback();
        }, errorCallback);
    };

    exports.getDirectory = function (successCallback, errorCallback, args) {
        var fullPath = args[0];
        var path = args[1];
        var options = args[2];

        // Create an absolute path if we were handed a relative one.
        path = resolveToFullPath_(fullPath, path);

        idb_.get(path.storagePath, function (folderEntry) {
            if (!options) {
                options = {};
            }

            if (options.create === true && options.exclusive === true && folderEntry) {
                // If create and exclusive are both true, and the path already exists,
                // getDirectory must fail.
                if (errorCallback) {
                    errorCallback(FileError.INVALID_MODIFICATION_ERR);
                }
            } else if (options.create === true && !folderEntry) {
                // If create is true, the path doesn't exist, and no other error occurs,
                // getDirectory must create it as a zero-length file and return a corresponding
                // MyDirectoryEntry.
                var dirEntry = new DirectoryEntry(path.fileName, path.fullPath, new FileSystem(path.fsName, fs_.root));

                idb_.put(dirEntry, path.storagePath, successCallback, errorCallback);
            } else if (options.create === true && folderEntry) {

                if (folderEntry.isDirectory) {
                    // IDB won't save methods, so we need re-create the MyDirectoryEntry.
                    successCallback(new DirectoryEntry(folderEntry.name, folderEntry.fullPath, folderEntry.fileSystem));
                } else {
                    if (errorCallback) {
                        errorCallback(FileError.INVALID_MODIFICATION_ERR);
                    }
                }
            } else if ((!options.create || options.create === false) && !folderEntry) {
                // Handle root special. It should always exist.
                if (path.fullPath === DIR_SEPARATOR) {
                    successCallback(fs_.root);
                    return;
                }

                // If create is not true and the path doesn't exist, getDirectory must fail.
                if (errorCallback) {
                    errorCallback(FileError.NOT_FOUND_ERR);
                }
            } else if ((!options.create || options.create === false) && folderEntry &&
                folderEntry.isFile) {
                // If create is not true and the path exists, but is a file, getDirectory
                // must fail.
                if (errorCallback) {
                    errorCallback(FileError.INVALID_MODIFICATION_ERR);
                }
            } else {
                // Otherwise, if no other error occurs, getDirectory must return a
                // MyDirectoryEntry corresponding to path.

                // IDB won't' save methods, so we need re-create MyDirectoryEntry.
                successCallback(new DirectoryEntry(folderEntry.name, folderEntry.fullPath, folderEntry.fileSystem));
            }
        }, errorCallback);
    };

    exports.getParent = function (successCallback, errorCallback, args) {
        var fullPath = args[0];

        if (fullPath === DIR_SEPARATOR) {
            successCallback(fs_.root);
            return;
        }

        var pathArr = fullPath.split(DIR_SEPARATOR);
        pathArr.pop();
        var namesa = pathArr.pop();
        var path = pathArr.join(DIR_SEPARATOR);

        exports.getDirectory(successCallback, errorCallback, [path, namesa, {create: false}]);
    };

    exports.copyTo = function (successCallback, errorCallback, args) {
        var srcPath = args[0];
        var parentFullPath = args[1];
        var name = args[2];

        // Read src file
        exports.getFile(function (srcFileEntry) {

            // Create dest file
            exports.getFile(function (dstFileEntry) {

                exports.write(function () {
                    successCallback(dstFileEntry);
                }, errorCallback, [dstFileEntry.file_.storagePath, srcFileEntry.file_.blob_, 0]);

            }, errorCallback, [parentFullPath, name, {create: true}]);

        }, errorCallback, [srcPath, null]);
    };

    exports.moveTo = function (successCallback, errorCallback, args) {
        var srcPath = args[0];
        // var parentFullPath = args[1];
        // var name = args[2];

        exports.copyTo(function (fileEntry) {

            exports.remove(function () {
                successCallback(fileEntry);
            }, errorCallback, [srcPath]);

        }, errorCallback, args);
    };

    exports.resolveLocalFileSystemURI = function (successCallback, errorCallback, args) {
        var path = args[0];

        // Ignore parameters
        if (path.indexOf('?') !== -1) {
            path = String(path).split('?')[0];
        }

        // support for encodeURI
        if (/\%5/g.test(path)) { // eslint-disable-line no-useless-escape
            path = decodeURI(path);
        }

        if (path.indexOf(pathsPrefix.dataDirectory) === 0) {
            path = path.substring(pathsPrefix.dataDirectory.length - 1);

            exports.requestFileSystem(function (fs) {
                fs.root.getFile(path, {create: false}, successCallback, function () {
                    fs.root.getDirectory(path, {create: false}, successCallback, errorCallback);
                });
            }, errorCallback, [LocalFileSystem.PERSISTENT]);
        } else if (path.indexOf(pathsPrefix.cacheDirectory) === 0) {
            path = path.substring(pathsPrefix.cacheDirectory.length - 1);

            exports.requestFileSystem(function (fs) {
                fs.root.getFile(path, {create: false}, successCallback, function () {
                    fs.root.getDirectory(path, {create: false}, successCallback, errorCallback);
                });
            }, errorCallback, [LocalFileSystem.TEMPORARY]);
        } else if (path.indexOf(pathsPrefix.applicationDirectory) === 0) {
            path = path.substring(pathsPrefix.applicationDirectory.length);

            var xhr = new XMLHttpRequest(); // eslint-disable-line no-undef
            xhr.open('GET', path, true);
            xhr.onreadystatechange = function () {
                if (xhr.status === 200 && xhr.readyState === 4) {
                    exports.requestFileSystem(function (fs) {
                        fs.name = location.hostname; // eslint-disable-line no-undef
                        fs.root.getFile(path, {create: true}, writeFile, errorCallback);
                    }, errorCallback, [LocalFileSystem.PERSISTENT]);
                }
            };

            xhr.onerror = function () {
                if (errorCallback) {
                    errorCallback(FileError.NOT_READABLE_ERR);
                }
            };

            xhr.send();
        } else {
            if (errorCallback) {
                errorCallback(FileError.NOT_FOUND_ERR);
            }
        }

        function writeFile (entry) {
            entry.createWriter(function (fileWriter) {
                fileWriter.onwriteend = function (evt) {
                    if (!evt.target.error) {
                        entry.filesystemName = location.hostname; // eslint-disable-line no-undef
                        successCallback(entry);
                    }
                };
                fileWriter.onerror = function () {
                    if (errorCallback) {
                        errorCallback(FileError.NOT_READABLE_ERR);
                    }
                };
                fileWriter.write(new Blob([xhr.response])); // eslint-disable-line no-undef
            }, errorCallback);
        }
    };

    exports.requestAllPaths = function (successCallback) {
        successCallback(pathsPrefix);
    };

/** * Helpers ***/

    /**
     * Interface to wrap the native File interface.
     *
     * This interface is necessary for creating zero-length (empty) files,
     * something the Filesystem API allows you to do. Unfortunately, File's
     * constructor cannot be called directly, making it impossible to instantiate
     * an empty File in JS.
     *
     * @param {Object} opts Initial values.
     * @constructor
     */
    function MyFile (opts) {
        var blob_ = new Blob(); // eslint-disable-line no-undef

        this.size = opts.size || 0;
        this.name = opts.name || '';
        this.type = opts.type || '';
        this.lastModifiedDate = opts.lastModifiedDate || null;
        this.storagePath = opts.storagePath || '';

        // Need some black magic to correct the object's size/name/type based on the
        // blob that is saved.
        Object.defineProperty(this, 'blob_', {
            enumerable: true,
            get: function () {
                return blob_;
            },
            set: function (val) {
                blob_ = val;
                this.size = blob_.size;
                this.name = blob_.name;
                this.type = blob_.type;
                this.lastModifiedDate = blob_.lastModifiedDate;
            }.bind(this)
        });
    }

    MyFile.prototype.constructor = MyFile;

    // When saving an entry, the fullPath should always lead with a slash and never
    // end with one (e.g. a directory). Also, resolve '.' and '..' to an absolute
    // one. This method ensures path is legit!
    function resolveToFullPath_ (cwdFullPath, path) {
        path = path || '';
        var fullPath = path;
        var prefix = '';

        cwdFullPath = cwdFullPath || DIR_SEPARATOR;
        /* eslint-disable no-undef */
        if (cwdFullPath.indexOf(FILESYSTEM_PREFIX) === 0) {
            prefix = cwdFullPath.substring(0, cwdFullPath.indexOf(DIR_SEPARATOR, FILESYSTEM_PREFIX.length));
            cwdFullPath = cwdFullPath.substring(cwdFullPath.indexOf(DIR_SEPARATOR, FILESYSTEM_PREFIX.length));
        }
        /* eslint-enable no-undef */
        var relativePath = path[0] !== DIR_SEPARATOR;
        if (relativePath) {
            fullPath = cwdFullPath;
            if (cwdFullPath !== DIR_SEPARATOR) {
                fullPath += DIR_SEPARATOR + path;
            } else {
                fullPath += path;
            }
        }

        // Adjust '..'s by removing parent directories when '..' flows in path.
        var parts = fullPath.split(DIR_SEPARATOR);
        for (var i = 0; i < parts.length; ++i) {
            var part = parts[i];
            if (part === '..') {
                parts[i - 1] = '';
                parts[i] = '';
            }
        }
        fullPath = parts.filter(function (el) {
            return el;
        }).join(DIR_SEPARATOR);

        // Add back in leading slash.
        if (fullPath[0] !== DIR_SEPARATOR) {
            fullPath = DIR_SEPARATOR + fullPath;
        }

        // Replace './' by current dir. ('./one/./two' -> one/two)
        fullPath = fullPath.replace(/\.\//g, DIR_SEPARATOR);

        // Replace '//' with '/'.
        fullPath = fullPath.replace(/\/\//g, DIR_SEPARATOR);

        // Replace '/.' with '/'.
        fullPath = fullPath.replace(/\/\./g, DIR_SEPARATOR);

        // Remove '/' if it appears on the end.
        if (fullPath[fullPath.length - 1] === DIR_SEPARATOR &&
            fullPath !== DIR_SEPARATOR) {
            fullPath = fullPath.substring(0, fullPath.length - 1);
        }

        return {
            storagePath: prefix + fullPath,
            fullPath: fullPath,
            fileName: fullPath.split(DIR_SEPARATOR).pop(),
            fsName: prefix.split(DIR_SEPARATOR).pop()
        };
    }

    function fileEntryFromIdbEntry (fileEntry) {
        // IDB won't save methods, so we need re-create the FileEntry.
        var clonedFileEntry = new FileEntry(fileEntry.name, fileEntry.fullPath, fileEntry.fileSystem);
        clonedFileEntry.file_ = fileEntry.file_;

        return clonedFileEntry;
    }

    function readAs (what, fullPath, encoding, startPos, endPos, successCallback, errorCallback) {
        exports.getFile(function (fileEntry) {
            var fileReader = new FileReader(); // eslint-disable-line no-undef
            var blob = fileEntry.file_.blob_.slice(startPos, endPos);

            fileReader.onload = function (e) {
                successCallback(e.target.result);
            };

            fileReader.onerror = errorCallback;

            switch (what) {
            case 'text':
                fileReader.readAsText(blob, encoding);
                break;
            case 'dataURL':
                fileReader.readAsDataURL(blob);
                break;
            case 'arrayBuffer':
                fileReader.readAsArrayBuffer(blob);
                break;
            case 'binaryString':
                fileReader.readAsBinaryString(blob);
                break;
            }

        }, errorCallback, [fullPath, null]);
    }

/** * Core logic to handle IDB operations ***/

    idb_.open = function (dbName, successCallback, errorCallback) {
        var self = this;

        // TODO: FF 12.0a1 isn't liking a db name with : in it.
        var request = indexedDB.open(dbName.replace(':', '_')/*, 1 /*version */);

        request.onerror = errorCallback || onError;

        request.onupgradeneeded = function (e) {
            // First open was called or higher db version was used.

            // console.log('onupgradeneeded: oldVersion:' + e.oldVersion,
            //           'newVersion:' + e.newVersion);

            self.db = e.target.result;
            self.db.onerror = onError;

            if (!self.db.objectStoreNames.contains(FILE_STORE_)) {
                self.db.createObjectStore(FILE_STORE_/*, {keyPath: 'id', autoIncrement: true} */);
            }
        };

        request.onsuccess = function (e) {
            self.db = e.target.result;
            self.db.onerror = onError;
            successCallback(e);
        };

        request.onblocked = errorCallback || onError;
    };

    idb_.close = function () {
        this.db.close();
        this.db = null;
    };

    idb_.get = function (fullPath, successCallback, errorCallback) {
        if (!this.db) {
            if (errorCallback) {
                errorCallback(FileError.INVALID_MODIFICATION_ERR);
            }
            return;
        }

        var tx = this.db.transaction([FILE_STORE_], 'readonly');

        // var request = tx.objectStore(FILE_STORE_).get(fullPath);
        var range = IDBKeyRange.bound(fullPath, fullPath + DIR_OPEN_BOUND,
            false, true);
        var request = tx.objectStore(FILE_STORE_).get(range);

        tx.onabort = errorCallback || onError;
        tx.oncomplete = function (e) {
            successCallback(request.result);
        };
    };

    idb_.getAllEntries = function (fullPath, storagePath, successCallback, errorCallback) {
        if (!this.db) {
            if (errorCallback) {
                errorCallback(FileError.INVALID_MODIFICATION_ERR);
            }
            return;
        }

        var results = [];

        if (storagePath[storagePath.length - 1] === DIR_SEPARATOR) {
            storagePath = storagePath.substring(0, storagePath.length - 1);
        }

        var range = IDBKeyRange.bound(
                storagePath + DIR_SEPARATOR, storagePath + DIR_OPEN_BOUND, false, true);

        var tx = this.db.transaction([FILE_STORE_], 'readonly');
        tx.onabort = errorCallback || onError;
        tx.oncomplete = function (e) {
            results = results.filter(function (val) {
                var valPartsLen = val.fullPath.split(DIR_SEPARATOR).length;
                var fullPathPartsLen = fullPath.split(DIR_SEPARATOR).length;

                if (fullPath === DIR_SEPARATOR && valPartsLen < fullPathPartsLen + 1) {
                    // Hack to filter out entries in the root folder. This is inefficient
                    // because reading the entires of fs.root (e.g. '/') returns ALL
                    // results in the database, then filters out the entries not in '/'.
                    return val;
                } else if (fullPath !== DIR_SEPARATOR &&
                    valPartsLen === fullPathPartsLen + 1) {
                    // If this a subfolder and entry is a direct child, include it in
                    // the results. Otherwise, it's not an entry of this folder.
                    return val;
                }
            });

            successCallback(results);
        };

        var request = tx.objectStore(FILE_STORE_).openCursor(range);

        request.onsuccess = function (e) {
            var cursor = e.target.result;
            if (cursor) {
                var val = cursor.value;

                results.push(val.isFile ? fileEntryFromIdbEntry(val) : new DirectoryEntry(val.name, val.fullPath, val.fileSystem));
                cursor['continue']();
            }
        };
    };

    idb_['delete'] = function (fullPath, successCallback, errorCallback) {
        if (!this.db) {
            if (errorCallback) {
                errorCallback(FileError.INVALID_MODIFICATION_ERR);
            }
            return;
        }

        var tx = this.db.transaction([FILE_STORE_], 'readwrite');
        tx.oncomplete = successCallback;
        tx.onabort = errorCallback || onError;

        // var request = tx.objectStore(FILE_STORE_).delete(fullPath);
        var range = IDBKeyRange.bound(
            fullPath, fullPath + DIR_OPEN_BOUND, false, true);
        tx.objectStore(FILE_STORE_)['delete'](range);
    };

    idb_.put = function (entry, storagePath, successCallback, errorCallback) {
        if (!this.db) {
            if (errorCallback) {
                errorCallback(FileError.INVALID_MODIFICATION_ERR);
            }
            return;
        }

        var tx = this.db.transaction([FILE_STORE_], 'readwrite');
        tx.onabort = errorCallback || onError;
        tx.oncomplete = function (e) {
            // TODO: Error is thrown if we pass the request event back instead.
            successCallback(entry);
        };

        tx.objectStore(FILE_STORE_).put(entry, storagePath);
    };

    // Global error handler. Errors bubble from request, to transaction, to db.
    function onError (e) {
        switch (e.target.errorCode) {
        case 12:
            console.log('Error - Attempt to open db with a lower version than the ' +
                    'current one.');
            break;
        default:
            console.log('errorCode: ' + e.target.errorCode);
        }

        console.log(e, e.code, e.message);
    }

// Clean up.
// TODO: Is there a place for this?
//    global.addEventListener('beforeunload', function(e) {
//        idb_.db && idb_.db.close();
//    }, false);

})(module.exports, window);

require('cordova/exec/proxy').add('File', module.exports);
