var clearSoup = function (soupName, successCB, errorCB) {
    storeConsole.debug("SmartStore.clearSoup: '" + soupName + "'");
    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "pgClearSoup",
         [{"soupName": soupName}]
        );
};
var reIndexSoup = function (soupName, paths, successCB, errorCB) {
    storeConsole.debug("SmartStore.reIndexSoup: '" + soupName + "' paths: " + JSON.stringify(paths));
    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "pgReIndexSoup",
         [{"soupName": soupName, "paths": paths}]
        );
};
var alterSoup = function (soupName, indexSpecs, reIndexData, successCB, errorCB) {
    storeConsole.debug("SmartStore.alterSoup: '" + soupName + "' indexSpecs: " + JSON.stringify(indexSpecs));
    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "pgAlterSoup",
         [{"soupName": soupName, "indexes": indexSpecs, "reIndexData": reIndexData}]
        );
};
var getSoupIndexSpecs = function(soupName, successCB, errorCB) {
    storeConsole.debug("SmartStore.getSoupIndexSpecs: " + soupName);
    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "pgGetSoupIndexSpecs",
         [{"soupName": soupName}]
        );
};
var soupExists = function (soupName, successCB, errorCB) {
    storeConsole.debug("SmartStore.soupExists: " + soupName);
    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "pgSoupExists",
         [{"soupName": soupName}]
        );
};
var removeStore = function (storeConfig,successCB, errorCB) {
    if (checkFirstArg(arguments)) return;
    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "pgRemoveStore",
         [{"isGlobalStore": storeConfig.isGlobalStore, "storeName": storeConfig.storeName}]
        );
};
var registerSoup = function (soupName, indexSpecs, successCB, errorCB) {
    console.log("SmartStore.registerSoup: '" + soupName + "' indexSpecs: " + JSON.stringify(indexSpecs));
    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "pgRegisterSoup",
         [{"soupName": soupName, "indexes": indexSpecs}]
        );
};
var moveCursorToPageIndex = function (cursor, newPageIndex, successCB, errorCB) {
    storeConsole.debug("moveCursorToPageIndex: " + cursor.cursorId + "  newPageIndex: " + newPageIndex);
    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "pgMoveCursorToPageIndex",
         [{"cursorId": cursor.cursorId, "index": newPageIndex}]
        );
};
var removeFromSoup = function (soupName, entryIds, successCB, errorCB) {
    storeConsole.debug("SmartStore.removeFromSoup: '" + soupName + "' entryIds: " + entryIds);
    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "pgRemoveFromSoup",
         [{"soupName": soupName, "entryIds": entryIds}]
        );
};
var closeCursor = function (cursor, successCB, errorCB) {
    storeConsole.debug("closeCursor: " + cursor.cursorId);
    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "pgCloseCursor",
         [{"cursorId": cursor.cursorId}]
        );
};
var upsertSoupEntriesWithExternalId = function (soupName, entries, externalIdPath, successCB, errorCB) {
    storeConsole.debug("SmartStore.upsertSoupEntries: '" + soupName + "' entries.length: " + entries.length);
    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "pgUpsertSoupEntries", 
         [{"soupName": soupName, "entries": entries, "externalIdPath": externalIdPath}]
        );
};
var syncDown = function(isGlobalStore, target, soupName, options, successCB, errorCB) {
    if (checkFirstArg(arguments)) return;
    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "syncDown",
         [{"target": target, "soupName": soupName, "options": options, "isGlobalStore":isGlobalStore}]
        );        
};
var reSync = function(isGlobalStore, syncId, successCB, errorCB) {
    if (checkFirstArg(arguments)) return;
    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "reSync",
         [{"syncId": syncId, "isGlobalStore":isGlobalStore}]
        );        
};
var getSyncStatus = function(isGlobalStore, syncId, successCB, errorCB) {
    if (checkFirstArg(arguments, "boolean", false)) return;
    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "getSyncStatus",
         [{"syncId": syncId, "isGlobalStore":isGlobalStore}]
        );        
};
var cleanResyncGhosts = function(storeConfig, syncId, successCB, errorCB) {
    if (checkFirstArg(arguments)) return;
    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "cleanResyncGhosts",
         [{"syncId": syncId,  "isGlobalStore": storeConfig.isGlobalStore, "storeName": storeConfig.storeName}]
        );
};
var syncUp = function(isGlobalStore, target, soupName, options, successCB, errorCB) {
    var args = Array.prototype.slice.call(arguments);
    // We accept syncUp(soupName, options, successCB, errorCB)
    if (typeof(args[0]) === "string") {
        isGlobalStore = false;
        target = {};
        soupName = args[0];
        options = args[1];
        successCB = args[2];
        errorCB = args[3];
    }
    // We accept syncUp(target, soupName, options, successCB, errorCB)
    if (typeof(args[0]) === "object") {
        isGlobalStore = false;
        target = args[0];
        soupName = args[1];
        options = args[2];
        successCB = args[3];
        errorCB = args[4];
    }
    target = target || {};

    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "syncUp",
         [{"target": target, "soupName": soupName, "options": options, "isGlobalStore":isGlobalStore}]
        );        
};
var syncUp = function(storeConfig, target, soupName, options, successCB, errorCB) {
    if (checkFirstArg(arguments)) return;
    var args = Array.prototype.slice.call(arguments);
    // We accept syncUp(soupName, options, successCB, errorCB)
    if (typeof(args[1]) === "string") {
        target = {};
        soupName = args[1];
        options = args[2];
        successCB = args[3];
        errorCB = args[4];
    }
    // We accept syncUp(target, soupName, options, successCB, errorCB)
    if (typeof(args[1]) === "object") {
        target = args[1];
        soupName = args[2];
        options = args[3];
        successCB = args[4];
        errorCB = args[5];
    }
    target = target || {};

    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "syncUp",
         [{"target": target, "soupName": soupName, "options": options,  "isGlobalStore": storeConfig.isGlobalStore, "storeName": storeConfig.storeName}]
        );
};
var removeSoup = function (soupName, successCB, errorCB) {
    storeConsole.debug("SmartStore.removeSoup: " + soupName);
    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "pgRemoveSoup",
         [{"soupName": soupName}]
        );
};
var closeCursor = function (isGlobalStore, cursor, successCB, errorCB) {
    if (checkFirstArg(arguments)) return;
    storeConsole.debug("closeCursor:isGlobalStore=" + isGlobalStore +",cursorId=" + cursor.cursorId);
    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "pgCloseCursor",
         [{"cursorId": cursor.cursorId, "isGlobalStore": isGlobalStore}]
        );
};
var moveCursorToPageIndex = function (isGlobalStore, cursor, newPageIndex, successCB, errorCB) {
    if (checkFirstArg(arguments)) return;
    storeConsole.debug("moveCursorToPageIndex:isGlobalStore=" + isGlobalStore +",cursorId=" + cursor.cursorId + ",newPageIndex=" + newPageIndex);
    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "pgMoveCursorToPageIndex",
         [{"cursorId": cursor.cursorId, "index": newPageIndex, "isGlobalStore": isGlobalStore}]
        );
};
var upsertSoupEntriesWithExternalId = function (isGlobalStore, soupName, entries, externalIdPath, successCB, errorCB) {
    if (checkFirstArg(arguments)) return;
    storeConsole.debug("SmartStore.upsertSoupEntries:isGlobalStore=" +isGlobalStore+ ",soupName=" + soupName + ",entries=" + entries.length + ",externalIdPath=" + externalIdPath);
    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "pgUpsertSoupEntries", 
         [{"soupName": soupName, "entries": entries, "externalIdPath": externalIdPath, "isGlobalStore": isGlobalStore}]
        );
};
var retrieveSoupEntries = function (isGlobalStore, soupName, entryIds, successCB, errorCB) {
    if (checkFirstArg(arguments)) return;
    storeConsole.debug("SmartStore.retrieveSoupEntries:isGlobalStore=" +isGlobalStore+ ",soupName=" + soupName + ",entryIds=" + entryIds);
    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "pgRetrieveSoupEntries",
         [{"soupName": soupName, "entryIds": entryIds, "isGlobalStore": isGlobalStore}]
        );
};
var soupExists = function (isGlobalStore, soupName, successCB, errorCB) {
    if (checkFirstArg(arguments)) return;
    storeConsole.debug("SmartStore.soupExists:isGlobalStore=" +isGlobalStore+ ",soupName=" + soupName);
    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "pgSoupExists",
         [{"soupName": soupName, "isGlobalStore": isGlobalStore}]
        );
};
var reIndexSoup = function (isGlobalStore, soupName, paths, successCB, errorCB) {
    if (checkFirstArg(arguments)) return;
    storeConsole.debug("SmartStore.reIndexSoup:isGlobalStore=" +isGlobalStore+ ",soupName=" + soupName + ",paths=" + JSON.stringify(paths));
    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "pgReIndexSoup",
         [{"soupName": soupName, "paths": paths, "isGlobalStore": isGlobalStore}]
        );
};
var alterSoup = function (isGlobalStore, soupName, indexSpecs, reIndexData, successCB, errorCB) {
    if (checkFirstArg(arguments)) return;
    storeConsole.debug("SmartStore.alterSoup:isGlobalStore=" +isGlobalStore+ ",soupName=" + soupName + ",indexSpecs=" + JSON.stringify(indexSpecs));
    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "pgAlterSoup",
         [{"soupName": soupName, "indexes": indexSpecs, "reIndexData": reIndexData, "isGlobalStore": isGlobalStore}]
        );
};
var runSmartQuery = function (querySpec, successCB, errorCB) {
    if (querySpec.queryType != "smart") throw new Error("runSmartQuery can only run smart queries");
    storeConsole.debug("SmartStore.runSmartQuery: smartSql: " + querySpec.smartSql);
    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "pgRunSmartQuery",
         [{"querySpec": querySpec}]
        );
};
var clearSoup = function (storeConfig, soupName, successCB, errorCB) {
    if (checkFirstArg(arguments)) return;
    storeConsole.debug("SmartStore.clearSoup:isGlobalStore=" + storeConfig.isGlobalStore + ",storeName=" + storeConfig.storeName + ",soupName=" + soupName);
    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "pgClearSoup",
         [{"soupName": soupName, "isGlobalStore": storeConfig.isGlobalStore, "storeName": storeConfig.storeName}]
        );
};
var registerSoupWithSpec = function (storeConfig, soupSpec, indexSpecs, successCB, errorCB) {
    if (checkFirstArg(arguments)) return;
    storeConsole.debug("SmartStore.registerSoupWithSpec:isGlobalStore=" + storeConfig.isGlobalStore + ",storeName=" + storeConfig.storeName + ",soupSpec="+ JSON.stringify(soupSpec) + ",indexSpecs=" + JSON.stringify(indexSpecs));
    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "pgRegisterSoup",
         [{"soupSpec": soupSpec, "indexes": indexSpecs, "isGlobalStore": storeConfig.isGlobalStore, "storeName": storeConfig.storeName}]
        );
};
var querySoup = function (soupName, querySpec, successCB, errorCB) {
    if (querySpec.queryType == "smart") throw new Error("Smart queries can only be run using runSmartQuery");
    storeConsole.debug("SmartStore.querySoup: '" + soupName + "' indexPath: " + querySpec.indexPath);
    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "pgQuerySoup",
         [{"soupName": soupName, "querySpec": querySpec}]
        );
};
var deleteSync = function(storeConfig, syncIdOrName, successCB, errorCB) {
    if (checkFirstArg(arguments, "boolean", false)) return;
    exec(SALESFORCE_MOBILE_SDK_VERSION, successCB, errorCB, SERVICE,
         "deleteSync",
         [{"syncId": typeof syncIdOrName === "string" ? null : syncIdOrName,
           "syncName": typeof syncIdOrName === "string" ? syncIdOrName : null,
           "isGlobalStore": storeConfig.isGlobalStore, "storeName": storeConfig.storeName}]
        );
};