import debounce from 'lodash/debounce';
import { MergeStateFunction } from './AdaptableReduxMerger';
import { AdaptableLogger } from '../../agGrid/AdaptableLogger';
import { buildAdaptableStateFunctionConfig } from './buildAdaptableStateFunctionConfig';
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 {
    adaptableId;
    adaptableStateKey;
    userName;
    initialState;
    loadState;
    persistState;
    constructor(config) {
        this.adaptableId = config.adaptableId;
        this.adaptableStateKey = config.adaptableStateKey;
        this.userName = config.userName;
        this.initialState = config.initialState;
        this.loadState = config.loadState;
        this.persistState = config.persistState;
        this.save =
            config.debounceStateDelay > 0
                ? debounce(this.save, config.debounceStateDelay, {
                    maxWait: 1000,
                })
                : this.save;
    }
    setStateKey(adaptableStateKey) {
        this.adaptableStateKey = adaptableStateKey;
    }
    load(adaptableInstance, initialState = this.initialState) {
        return (this.loadState || loadState)(buildAdaptableStateFunctionConfig(adaptableInstance)).then((parsedJsonState) => {
            // we need to merge the Initial Adaptable State
            return Promise.resolve(initialState)
                .then((parsedInitialState) => {
                return MergeStateFunction(parsedInitialState, parsedJsonState);
            })
                .catch((err) => AdaptableLogger.consoleErrorBase(`AdaptableId: ${this.adaptableId}`, err));
        });
    }
    save(adaptableInstance, state, actionName) {
        if (!adaptableInstance || adaptableInstance.isDestroyed) {
            return Promise.resolve();
        }
        return this.saveNow(adaptableInstance, state, actionName);
    }
    saveNow(adaptableInstance, state, actionName) {
        const config = buildAdaptableStateFunctionConfig(adaptableInstance);
        config.actionName = actionName;
        config.previousState = adaptableInstance.adaptableStore.getPreviousStorageState() || null;
        let stateObject = structuredClone(state);
        const getTransformedState = adaptableInstance.adaptableOptions.stateOptions.saveState;
        if (getTransformedState) {
            stateObject = getTransformedState(stateObject, config);
        }
        const promise = (this.persistState || persistState)(stateObject, config)?.catch(rejectWithMessage);
        if (!(promise instanceof Promise)) {
            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);
}
export function createEngine(config) {
    return new AdaptableReduxLocalStorageEngine(config);
}
