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

/** @module store/indexeddb */
var utils = require('./../odatajs.js').utils;

// Imports.
var throwErrorCallback = utils.throwErrorCallback;
var delay = utils.delay;


var indexedDB = utils.inBrowser() ? window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB || window.indexedDB : undefined;
var IDBKeyRange = utils.inBrowser() ? window.IDBKeyRange || window.webkitIDBKeyRange : undefined;
var IDBTransaction = utils.inBrowser() ? window.IDBTransaction || window.webkitIDBTransaction || {} : {} ;

var IDBT_READ_ONLY = IDBTransaction.READ_ONLY || "readonly";
var IDBT_READ_WRITE = IDBTransaction.READ_WRITE || "readwrite";

/** Returns either a specific error handler or the default error handler
 * @param {Function} error - The specific error handler
 * @param {Function} defaultError - The default error handler
 * @returns {Function} The error callback
 */
function getError(error, defaultError) {

    return function (e) {
        var errorFunc = error || defaultError;
        if (!errorFunc) {
            return;
        }

        // Old api quota exceeded error support.
        if (Object.prototype.toString.call(e) === "[object IDBDatabaseException]") {
            if (e.code === 11 /* IndexedDb disk quota exceeded */) {
                errorFunc({ name: "QuotaExceededError", error: e });
                return;
            }
            errorFunc(e);
            return;
        }

        var errName;
        try {
            var errObj = e.target.error || e;
            errName = errObj.name;
        } catch (ex) {
            errName = (e.type === "blocked") ? "IndexedDBBlocked" : "UnknownError";
        }
        errorFunc({ name: errName, error: e });
    };
}

/** Opens the store object's indexed db database.
 * @param {IndexedDBStore} store - The store object
 * @param {Function} success - The success callback
 * @param {Function} error - The error callback
 */
function openStoreDb(store, success, error) {

    var storeName = store.name;
    var dbName = "_datajs_" + storeName;

    var request = indexedDB.open(dbName);
    request.onblocked = error;
    request.onerror = error;

    request.onupgradeneeded = function () {
        var db = request.result;
        if (!db.objectStoreNames.contains(storeName)) {
            db.createObjectStore(storeName);
        }
    };

    request.onsuccess = function (event) {
        var db = request.result;
        if (!db.objectStoreNames.contains(storeName)) {
            // Should we use the old style api to define the database schema?
            if ("setVersion" in db) {
                var versionRequest = db.setVersion("1.0");
                versionRequest.onsuccess = function () {
                    var transaction = versionRequest.transaction;
                    transaction.oncomplete = function () {
                        success(db);
                    };
                    db.createObjectStore(storeName, null, false);
                };
                versionRequest.onerror = error;
                versionRequest.onblocked = error;
                return;
            }

            // The database doesn't have the expected store.
            // Fabricate an error object for the event for the schema mismatch
            // and error out.
            event.target.error = { name: "DBSchemaMismatch" };
            error(event);
            return;
        }

        db.onversionchange = function(event) {
            event.target.close();
        };
        success(db);
    };
}

/** Opens a new transaction to the store
 * @param {IndexedDBStore} store - The store object
 * @param {Short} mode - The read/write mode of the transaction (constants from IDBTransaction)
 * @param {Function} success - The success callback
 * @param {Function} error - The error callback
 */
function openTransaction(store, mode, success, error) {

    var storeName = store.name;
    var storeDb = store.db;
    var errorCallback = getError(error, store.defaultError);

    if (storeDb) {
        success(storeDb.transaction(storeName, mode));
        return;
    }

    openStoreDb(store, function (db) {
        store.db = db;
        success(db.transaction(storeName, mode));
    }, errorCallback);
}

/** Creates a new IndexedDBStore.
 * @class IndexedDBStore
 * @constructor
 * @param {String} name - The name of the store.
 * @returns {Object} The new IndexedDBStore.
 */
function IndexedDBStore(name) {
    this.name = name;
}

/** Creates a new IndexedDBStore.
 * @method module:store/indexeddb~IndexedDBStore.create
 * @param {String} name - The name of the store.
 * @returns {Object} The new IndexedDBStore.
 */
IndexedDBStore.create = function (name) {
    if (IndexedDBStore.isSupported()) {
        return new IndexedDBStore(name);
    }

    throw { message: "IndexedDB is not supported on this browser" };
};

/** Returns whether IndexedDB is supported.
 * @method module:store/indexeddb~IndexedDBStore.isSupported
 * @returns {Boolean} True if IndexedDB is supported, false otherwise.
 */
IndexedDBStore.isSupported = function () {
    return !!indexedDB;
};

/** Adds a key/value pair to the store
 * @method module:store/indexeddb~IndexedDBStore#add
 * @param {String} key - The key
 * @param {Object} value - The value
 * @param {Function} success - The success callback
 * @param {Function} error - The error callback
*/
IndexedDBStore.prototype.add = function (key, value, success, error) {
    var name = this.name;
    var defaultError = this.defaultError;
    var keys = [];
    var values = [];

    if (key instanceof Array) {
        keys = key;
        values = value;
    } else {
        keys = [key];
        values = [value];
    }

    openTransaction(this, IDBT_READ_WRITE, function (transaction) {
        transaction.onabort = getError(error, defaultError, key, "add");
        transaction.oncomplete = function () {
            if (key instanceof Array) {
                success(keys, values);
            } else {
                success(key, value);
            }
        };

        for (var i = 0; i < keys.length && i < values.length; i++) {
            transaction.objectStore(name).add({ v: values[i] }, keys[i]);
        }
    }, error);
};

/** Adds or updates a key/value pair in the store
 * @method module:store/indexeddb~IndexedDBStore#addOrUpdate
 * @param {String} key - The key
 * @param {Object} value - The value
 * @param {Function} success - The success callback
 * @param {Function} error - The error callback
 */
IndexedDBStore.prototype.addOrUpdate = function (key, value, success, error) {
    var name = this.name;
    var defaultError = this.defaultError;
    var keys = [];
    var values = [];

    if (key instanceof Array) {
        keys = key;
        values = value;
    } else {
        keys = [key];
        values = [value];
    }

    openTransaction(this, IDBT_READ_WRITE, function (transaction) {
        transaction.onabort = getError(error, defaultError);
        transaction.oncomplete = function () {
            if (key instanceof Array) {
                success(keys, values);
            } else {
                success(key, value);
            }
        };

        for (var i = 0; i < keys.length && i < values.length; i++) {
            var record = { v: values[i] };
            transaction.objectStore(name).put(record, keys[i]);
        }
    }, error);
};

/** Clears the store
 * @method module:store/indexeddb~IndexedDBStore#clear
 * @param {Function} success - The success callback
 * @param {Function} error - The error callback
 */
IndexedDBStore.prototype.clear = function (success, error) {
    var name = this.name;
    var defaultError = this.defaultError;
    openTransaction(this, IDBT_READ_WRITE, function (transaction) {
        transaction.onerror = getError(error, defaultError);
        transaction.oncomplete = function () {
            success();
        };

        transaction.objectStore(name).clear();
    }, error);
};
/** Closes the connection to the database
 * @method module:store/indexeddb~IndexedDBStore#close
*/
IndexedDBStore.prototype.close = function () {
    
    if (this.db) {
        this.db.close();
        this.db = null;
    }
};

/** Returns whether the store contains a key
 * @method module:store/indexeddb~IndexedDBStore#contains
 * @param {String} key - The key
 * @param {Function} success - The success callback
 * @param {Function} error - The error callback
 */
IndexedDBStore.prototype.contains = function (key, success, error) {
    var name = this.name;
    var defaultError = this.defaultError;
    openTransaction(this, IDBT_READ_ONLY, function (transaction) {
        var objectStore = transaction.objectStore(name);
        var request = objectStore.get(key);

        transaction.oncomplete = function () {
            success(!!request.result);
        };
        transaction.onerror = getError(error, defaultError);
    }, error);
};

IndexedDBStore.prototype.defaultError = throwErrorCallback;

/** Gets all the keys from the store
 * @method module:store/indexeddb~IndexedDBStore#getAllKeys
 * @param {Function} success - The success callback
 * @param {Function} error - The error callback
 */
IndexedDBStore.prototype.getAllKeys = function (success, error) {
    var name = this.name;
    var defaultError = this.defaultError;
    openTransaction(this, IDBT_READ_WRITE, function (transaction) {
        var results = [];

        transaction.oncomplete = function () {
            success(results);
        };

        var request = transaction.objectStore(name).openCursor();

        request.onerror = getError(error, defaultError);
        request.onsuccess = function (event) {
            var cursor = event.target.result;
            if (cursor) {
                results.push(cursor.key);
                // Some tools have issues because continue is a javascript reserved word.
                cursor["continue"].call(cursor);
            }
        };
    }, error);
};

/** Identifies the underlying mechanism used by the store.
*/
IndexedDBStore.prototype.mechanism = "indexeddb";

/** Reads the value for the specified key
 * @method module:store/indexeddb~IndexedDBStore#read
 * @param {String} key - The key
 * @param {Function} success - The success callback
 * @param {Function} error - The error callback
 * If the key does not exist, the success handler will be called with value = undefined
 */
IndexedDBStore.prototype.read = function (key, success, error) {
    var name = this.name;
    var defaultError = this.defaultError;
    var keys = (key instanceof Array) ? key : [key];

    openTransaction(this, IDBT_READ_ONLY, function (transaction) {
        var values = [];

        transaction.onerror = getError(error, defaultError, key, "read");
        transaction.oncomplete = function () {
            if (key instanceof Array) {
                success(keys, values);
            } else {
                success(keys[0], values[0]);
            }
        };

        for (var i = 0; i < keys.length; i++) {
            // Some tools have issues because get is a javascript reserved word. 
            var objectStore = transaction.objectStore(name);
            var request = objectStore.get.call(objectStore, keys[i]);
            request.onsuccess = function (event) {
                var record = event.target.result;
                values.push(record ? record.v : undefined);
            };
        }
    }, error);
};

/** Removes the specified key from the store
 * @method module:store/indexeddb~IndexedDBStore#remove
 * @param {String} key - The key
 * @param {Function} success - The success callback
 * @param {Function} error - The error callback
 */
IndexedDBStore.prototype.remove = function (key, success, error) {

    var name = this.name;
    var defaultError = this.defaultError;
    var keys = (key instanceof Array) ? key : [key];

    openTransaction(this, IDBT_READ_WRITE, function (transaction) {
        transaction.onerror = getError(error, defaultError);
        transaction.oncomplete = function () {
            success();
        };

        for (var i = 0; i < keys.length; i++) {
            // Some tools have issues because continue is a javascript reserved word.
            var objectStore = transaction.objectStore(name);
            objectStore["delete"].call(objectStore, keys[i]);
        }
    }, error);
};

/** Updates a key/value pair in the store
 * @method module:store/indexeddb~IndexedDBStore#update
 * @param {String} key - The key
 * @param {Object} value - The value
 * @param {Function} success - The success callback
 * @param {Function} error - The error callback
 */
IndexedDBStore.prototype.update = function (key, value, success, error) {
    var name = this.name;
    var defaultError = this.defaultError;
    var keys = [];
    var values = [];

    if (key instanceof Array) {
        keys = key;
        values = value;
    } else {
        keys = [key];
        values = [value];
    }

    openTransaction(this, IDBT_READ_WRITE, function (transaction) {
        transaction.onabort = getError(error, defaultError);
        transaction.oncomplete = function () {
            if (key instanceof Array) {
                success(keys, values);
            } else {
                success(key, value);
            }
        };

        for (var i = 0; i < keys.length && i < values.length; i++) {
            var request = transaction.objectStore(name).openCursor(IDBKeyRange.only(keys[i]));
            var record = { v: values[i] };
            request.pair = { key: keys[i], value: record };
            request.onsuccess = function (event) {
                var cursor = event.target.result;
                if (cursor) {
                    cursor.update(event.target.pair.value);
                } else {
                    transaction.abort();
                }
            }
        }
    }, error);
};


module.exports = IndexedDBStore;