/*!
 * Copyright 2017 - 2020 by ChartIQ, Inc.
 * All rights reserved.
 */
/**
 * The Storage Client handles saving and retrieving data for your smart desktop.
 *
 *
 * See the <a href="/docs/productivity/API-tutorials-and-refs/storage/storingData">Storing Data tutorial</a> for an overview of using the Storage Client.
 * @module StorageClient
 */
import { Logger } from "./logger";
import { promisify } from "../common/util";
import { RouterClient } from "./routerClient";
import SystemManagerClient from "../common/systemManagerClient";
import pLimit from "p-limit";
const limit = pLimit(1);
/**
 * Logs an "info" level log unless it's an error, in which case it logs a "error" level log
 */
const log = (err, ...args) => {
    const logMethod = err ? Logger.system.error : Logger.system.info;
    logMethod(...args, err);
};
/**
 * @language javascript, java, dotnet
 * Define the user name for storage (i.e., each user has unique storage).
 *
 * ```javascript
 * FSBL.Clients.StorageClient.setUser({ user: "JohnDeere"});
 * ```
 * @param params
 * @param params.user A unique key to store user data under
 * @param cb Callback to be called on success.
 */
export const setUser = async (params, cb) => {
    await SystemManagerClient.waitForStartup("storageService");
    const { err, response } = await RouterClient.query("Storage.setUser", { user: params.user });
    log(err, "APPLICATION LIFECYCLE:StorageClient.setUser", params, err, response.data);
    cb === null || cb === void 0 ? void 0 : cb(err);
    return { err };
};
/**
 * @language javascript, java, dotnet
 * @deprecated This method has been deprecated.
 *
 * Specifies the data store. For normal operation you don't have to invoke this function.
 * The default data store is set in configuration.
 *
 * ```javascript
 * FSBL.Clients.StorageClient.setStore({topic:"finsemble", dataStore:"redis"})
 * ```
 * @param params
 * @param params.topic If specified then data store is set only for topic.
 * @param params.dataStore Identifies the data store (e.g. "localStorage", "redis").
 * @param cb Callback to be called on success.
 * @ignore
 */
export const setStore = async (params, cb) => {
    Logger.deprecated("StorageClient.setStore() has been deprecated and will be removed in a future release");
    Logger.system.log("APPLICATION LIFECYCLE:StorageClient.setStore", params, cb);
    await SystemManagerClient.waitForStartup("storageService");
    const { err, response } = await RouterClient.query("Storage.setStore", params);
    log(err, "Storage.setStore", response);
    // Always returns { status: "success"}. Not useful but leaving for strict backward compatibility.
    cb === null || cb === void 0 ? void 0 : cb(err, response.data);
    return { err, data: response.data };
};
/**
 * @language javascript, java, dotnet
 * Save a key value pair into storage.
 *
 * ```javascript
 * FSBL.Clients.StorageClient.save({topic:"finsemble", key:"testKey", value:"testValue"});
 * FSBL.Clients.StorageClient.save({topic:"finsemble", key:"testKey", value:"testValue"}, (err, data) => {});
 * const {err, data} = await FSBL.Clients.StorageClient.save({topic:"finsemble", key:"testKey", value:"testValue"});
 * ```
 * @param params
 * @param params.topic Storage topic for key being stored.
 * @param params.key The key for the value to be stored under.
 * @param params.value The value to be stored.
 * @param cb Callback to be called on success.
 */
export const save = async (params, cb) => {
    if (typeof params.key !== "string" || typeof params.topic !== "string") {
        throw new Error("Values for key and topic must be strings.");
    }
    await SystemManagerClient.waitForStartup("storageService");
    const { err, response } = await RouterClient.query("Storage.save", params);
    log(err, "Storage.save", response.data);
    // data is not useful in response but retaining for strict backward compatibility
    cb === null || cb === void 0 ? void 0 : cb(err, response.data);
    if (err)
        throw err; // Backward compatibility
    return { err, data: response.data };
};
/**
 * @language javascript
 * Get a value from storage.
 *
 * ```javascript
 * FSBL.Clients.StorageClient.getStandardized({ topic:"finsemble", key:"testKey" }, function(err, data) {
 *	let myData = data;
 * });
 * const {err, data} = await FSBL.Clients.StorageClient.getStandardized({ topic:"finsemble", key:"testKey" });
 * ```
 * @param params
 * @param params.key The key to get from storage.
 * @param params.topic The topic that the data is saved under.
 * @param cb Callback to be called on success.
 */
export const getStandardized = async (params, cb) => {
    if (typeof params.key !== "string" || typeof params.topic !== "string") {
        throw new Error("Values for key and topic must be strings.");
    }
    await SystemManagerClient.waitForStartup("storageService");
    const { err, response } = await RouterClient.query("Storage.get", params);
    log(err, "Storage.get", response.data);
    cb === null || cb === void 0 ? void 0 : cb(err, response.data);
    return { err, data: response.data };
};
/**
 * @language javascript, java, dotnet
 * @deprecated Use [getStandardized()](#getstandardized) for a standardized `Promise<{err, data}>`
 *
 * This function returns a `Promise<T>` and rejects on an error. This is maintained for backward compatibility.
 *
 * Get a value from storage.
 *
 * ```javascript
 * FSBL.Clients.StorageClient.get({ topic:"finsemble", key:"testKey" }, function(err, data) {
 *	var myData = data;
 * });
 * ```
 *
 * @param params
 * @param params.key The key to get from storage.
 * @param params.topic The topic that the data is saved under.
 * @param cb Callback to be called on success.
 */
export const get = async (params, cb) => {
    Logger.system.deprecated("FSBL.Clients.StorageClient.get is is no longer supported and will likely go away in the future. Use FSBL.Clients.StorageClient.getStandardized() instead.");
    const { err, data } = await getStandardized(params);
    cb === null || cb === void 0 ? void 0 : cb(err, data);
    if (err)
        throw err;
    // backward compatibility
    else
        return data;
};
/**
 * @language javascript, java, dotnet
 * Get all keys for the topic.
 *
 * ```javascript
 * FSBL.Clients.StorageClient.keys({topic:"finsemble", keyPrefix:"test"}, function(err, data){
 *	let myKeys = data;
 * });
 * const {err, data} = await FSBL.Clients.StorageClient.keys({topic:"finsemble", keyPrefix:"test"});
 * ```
 * @param params
 * @param params.topic Topic for the keys to return.
 * @param params.keyPrefix Filter all keys that don't start with this prefix.
 * @param cb Callback to be called on success.
 */
export const keys = async (params, cb) => {
    Logger.system.debug("StorageClient.keys", params, cb);
    await SystemManagerClient.waitForStartup("storageService");
    const { err, response } = await RouterClient.query("Storage.keys", params);
    log(err, "Storage.keys", response.data);
    cb === null || cb === void 0 ? void 0 : cb(err, response.data);
    return { err, data: response.data };
};
/**
 * @language javascript
 * @deprecated
 *
 * Get a multiple values from storage based on regex.
 * @param params
 * @param cb Callback to be called on success.
 * @ignore
 */
export const getMultiple = async (params, cb) => {
    Logger.deprecated("StorageClient.getMultiple() is deprecated and will be removed in a future release");
    Logger.system.info("StorageClient.getMultiple", params, cb);
    await SystemManagerClient.waitForStartup("storageService");
    const { err, response } = await RouterClient.query("Storage.getMultiple", params);
    log(err, "StorageClient.getMultiple:", params, response);
    cb === null || cb === void 0 ? void 0 : cb(err, response); // Strict backward compatibility
    return { err, data: response.data };
};
/**
 * @language javascript, java, dotnet
 * Delete a value from storage.
 *
 * ```javascript
 * FSBL.Clients.StorageClient.remove({ key:"testKey" })
 * await FSBL.Clients.StorageClient.remove({ key:"testKey" })
 * ```
 * @param params
 * @param params.key The key to get from storage.
 * @param params.topic The topic that the data is saved under.
 * @param cb Callback to be called on success.
 */
export const remove = async (params, cb) => {
    await SystemManagerClient.waitForStartup("storageService");
    const { err, response } = await RouterClient.query("Storage.delete", params);
    log(err, "StorageClient.delete", response.data);
    cb === null || cb === void 0 ? void 0 : cb(err, response.data);
    if (err)
        throw err; // Strict backward compatibility
    return { err, data: response.data };
};
/**
 * Rate limited storage save
 * @deprecated
 */
const save1 = (params) => {
    Logger.deprecated("StorageClient.save1() is deprecated and will be removed in a future release");
    limit(() => save(params));
};
/**
 * Rate limited get. This will be moved into windowStorageManager
 * @deprecated
 */
const get1 = (params, cb) => {
    Logger.deprecated("StorageClient.get1() is deprecated and will be removed in a future release");
    return limit(() => get(params, cb));
};
/**
 * @deprecated
 */
const keys1 = (params) => {
    Logger.deprecated("StorageClient.keys1() is deprecated and will be removed in a future release");
    return limit(() => promisify(keys)(params));
};
/**
 * Rate limited remove()
 * @deprecated
 */
const remove1 = (params) => {
    Logger.deprecated("StorageClient.remove1() is deprecated and will be removed in a future release");
    limit(() => remove(params));
};
/**
 * @language javascript
 * @deprecated
 * @ignore
 */
export const deleteInner = (...args) => {
    Logger.deprecated("StorageClient.delete() is deprecated and will be removed in a future release");
    remove.apply(args);
};
/**
 * @language javascript, java, dotnet
 * Clears a storage adapter of all data.
 * @param cb The callback to be invoked after the method completes successfully.
 * @param params
 * @param params.topic The storage topic that the data is cleared under.
 */
export const clearCache = async (cb, params) => {
    Logger.system.log("StorageClient.clearCache", cb, params);
    await SystemManagerClient.waitForStartup("storageService");
    const { err, response } = await RouterClient.query("Storage.clearCache", params !== null && params !== void 0 ? params : null);
    log(err, "StorageClient.clearCache", response.data);
    cb === null || cb === void 0 ? void 0 : cb(err, response.data); // return result is not useful but keeping for strict backward compatibility
    return { err, data: response.data };
};
/**
 * @ignore
 */
export const StorageClient = {
    /**
     * For backward compatibility
     * @private
     * @deprecated
     */
    initialize: () => {
        Logger.system.deprecated("It is no longer necessary to call StorageClient.initialized()");
    },
    /**
     * For backward compatibility
     * @private
     * @deprecated
     */
    onReady: (cb) => {
        Logger.system.deprecated("It is no longer necessary to call StorageClient.onReady()");
        cb === null || cb === void 0 ? void 0 : cb();
    },
    clearCache,
    remove,
    getMultiple,
    keys,
    getStandardized,
    get,
    save,
    setStore,
    setUser,
    delete: deleteInner,
    remove1,
    get1,
    save1,
    keys1,
};
/**
 * @ignore
 */
export default StorageClient;
//# sourceMappingURL=storageClient.js.map