"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createEngine = void 0;
const tslib_1 = require("tslib");
const debounce_1 = tslib_1.__importDefault(require("lodash/debounce"));
const AdaptableReduxMerger_1 = require("./AdaptableReduxMerger");
const StringExtensions_1 = require("../../Utilities/Extensions/StringExtensions");
const AdaptableLogger_1 = require("../../agGrid/AdaptableLogger");
const checkStatus = (response) => {
    const error = new Error(response.statusText);
    if (response.status >= 200 && response.status < 300) {
        return response;
    }
    throw error;
};
const persistState = (state, config) => {
    return new Promise((resolve, reject) => {
        try {
            localStorage.setItem(config.adaptableStateKey, JSON.stringify(state));
            resolve();
        }
        catch (ex) {
            reject(ex);
        }
    });
};
const loadState = ({ adaptableId, adaptableStateKey }) => {
    const jsonState = localStorage.getItem(adaptableStateKey);
    const parsedJsonState = JSON.parse(jsonState) || {};
    return Promise.resolve(parsedJsonState);
};
class AdaptableReduxLocalStorageEngine {
    constructor(config) {
        this.adaptableId = config.adaptableId;
        this.adaptableStateKey = config.adaptableStateKey;
        this.userName = config.userName;
        this.predefinedConfig = config.predefinedConfig;
        this.loadState = config.loadState;
        this.persistState = config.persistState;
        this.save =
            config.debounceStateDelay > 0
                ? (0, debounce_1.default)(this.save, config.debounceStateDelay, {
                    maxWait: 1000,
                })
                : this.save;
    }
    setStateKey(adaptableStateKey) {
        this.adaptableStateKey = adaptableStateKey;
    }
    load(predefinedConfig = this.predefinedConfig) {
        return (this.loadState || loadState)({
            adaptableId: this.adaptableId,
            adaptableStateKey: this.adaptableStateKey,
            userName: this.userName,
        }).then((parsedJsonState) => {
            if (typeof predefinedConfig === 'string' &&
                StringExtensions_1.StringExtensions.IsNotNullOrEmpty(predefinedConfig)) {
                // we have config in a file so lets merge it with the other state
                return fetch(predefinedConfig)
                    .then(checkStatus)
                    .then((response) => response.json())
                    .then((parsedPredefinedState) => {
                    return (0, AdaptableReduxMerger_1.MergeStateFunction)(parsedPredefinedState, parsedJsonState);
                })
                    .catch((err) => AdaptableLogger_1.AdaptableLogger.consoleErrorBase(`AdaptableId: ${this.adaptableId}`, err));
            }
            if (predefinedConfig != null) {
                // we have config as an object so need to merge that
                return Promise.resolve(predefinedConfig)
                    .then((parsedPredefinedState) => {
                    return (0, AdaptableReduxMerger_1.MergeStateFunction)(parsedPredefinedState, parsedJsonState);
                })
                    .catch((err) => AdaptableLogger_1.AdaptableLogger.consoleErrorBase(`AdaptableId: ${this.adaptableId}`, err));
            }
            // no predefined config so nothing to merge
            return new Promise((resolve) => {
                resolve(!!parsedJsonState ? (0, AdaptableReduxMerger_1.AddStateSource)(parsedJsonState, 'User') : {});
            }).catch(rejectWithMessage);
        });
    }
    save(state, getState) {
        return this.saveNow(state, getState);
    }
    saveNow(state, getState) {
        var _a;
        const config = {
            adaptableId: this.adaptableId,
            adaptableStateKey: this.adaptableStateKey,
            userName: this.userName,
        };
        let result = state;
        if (getState) {
            result = getState(state, config);
        }
        const promise = (_a = (this.persistState || persistState)(result, config)) === null || _a === void 0 ? void 0 : _a.catch(rejectWithMessage);
        if (!(promise instanceof Promise)) {
            AdaptableLogger_1.AdaptableLogger.consoleWarnBase(`AdaptableId: ${this.adaptableId}`, 'stateOptions.persistState should return a promise, it returned', 'Error', promise);
        }
        return promise;
    }
}
function rejectWithMessage(error) {
    return Promise.reject(error.message);
}
function createEngine(config) {
    return new AdaptableReduxLocalStorageEngine(config);
}
exports.createEngine = createEngine;
