"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.areStatesEqual = exports.getStateFromUrl = exports.updateUrl = void 0;
var tslib_1 = require("tslib");
var lodash_debounce_1 = tslib_1.__importDefault(require("lodash.debounce"));
var array_1 = require("../utils/array");
var url_1 = require("../utils/url");
var S_DELIM = "_"; //This is the current layer/group name delimiter
// Firefox does not like us hammering window.history.replaceState() willy-nilly, so wrap it in a debounced version
// 100ms should be sufficient breathing space
var debouncedReplaceState = (0, lodash_debounce_1.default)(function (state, _, url) { return window.history.replaceState(state, _, url); }, 100);
/**
 * Updates the main URL with the given application state. If passing extra custom state,
 * this extra custom state is also included when getStateFromUrl() is called.
 *
 * Also if the custom state shares the same keys as the main application state, the application
 * state takes precedence (ie. The key/value in the custom state *will not* overwrite the application state for the same key).
 *
 * To avoid this, you should delete/omit said keys from the application state when calling this method if
 * you want to take the equivalent key/value from the custom state.
 *
 * @export
 * @param {IAppUrlState} state
 * @param {*} [extraState] Any extra state to include into the main URL
 * @param {string[] | undefined} ignoreProps Do not write the following properties to the URL
 *
 * @since 0.13
 * @since 0.14 - New optional extraState argument
 * @since 0.14.9 - New optional ignoreProps argument
 */
function updateUrl(state, extraState, ignoreProps) {
    var st = tslib_1.__assign({}, extraState);
    for (var k in state) {
        if (ignoreProps && ignoreProps.indexOf(k) >= 0)
            continue;
        var val = state[k];
        switch (k) {
            case "ft":
                st.ft = (val == true) ? 1 : 0;
                break;
            case "sl":
                st.sl = val === null || val === void 0 ? void 0 : val.join(S_DELIM);
                break;
            case "hl":
                st.hl = val === null || val === void 0 ? void 0 : val.join(S_DELIM);
                break;
            case "sg":
                st.sg = val === null || val === void 0 ? void 0 : val.join(S_DELIM);
                break;
            case "hg":
                st.hg = val === null || val === void 0 ? void 0 : val.join(S_DELIM);
                break;
            default:
                st[k] = val;
                break;
        }
    }
    var url = (0, url_1.appendParameters)(window.location.href, st, true, false, ignoreProps != null);
    //window.history.replaceState(st, "", url);
    debouncedReplaceState(st, "", url);
}
exports.updateUrl = updateUrl;
/**
 * Gets the application state from the current main URL. If the URL was updated with custom state
 * via updateUrl(), they will also be included in the returned state.
 *
 * @export
 * @param {string[]} [ignoreKeys]
 * @returns {IAppUrlState}
 * @since 0.13
 * @since 0.14 - New optional ignoreKeys to avoid reading out certain properties from URL state
 */
function getStateFromUrl(ignoreKeys) {
    var st = (0, url_1.parseUrlParameters)(window.location.href);
    var state = {};
    var ignore = ignoreKeys !== null && ignoreKeys !== void 0 ? ignoreKeys : [];
    for (var k in st) {
        if (ignore.indexOf(k) >= 0) {
            continue;
        }
        var val = st[k];
        switch (k) {
            case "ft":
                {
                    var n = parseInt(val, 10);
                    if (!isNaN(n)) {
                        state.ft = (n == 0) ? false : true;
                    }
                }
                break;
            case "x":
                {
                    var n = parseFloat(val);
                    if (!isNaN(n)) {
                        state.x = n;
                    }
                }
                break;
            case "y":
                {
                    var n = parseFloat(val);
                    if (!isNaN(n)) {
                        state.y = n;
                    }
                }
                break;
            case "scale":
                {
                    var n = parseFloat(val);
                    if (!isNaN(n)) {
                        state.scale = n;
                    }
                }
                break;
            case "sl":
                state.sl = val === null || val === void 0 ? void 0 : val.split(S_DELIM);
                break;
            case "hl":
                state.hl = val === null || val === void 0 ? void 0 : val.split(S_DELIM);
                break;
            case "sg":
                state.sg = val === null || val === void 0 ? void 0 : val.split(S_DELIM);
                break;
            case "hg":
                state.hg = val === null || val === void 0 ? void 0 : val.split(S_DELIM);
                break;
            default:
                state[k] = val;
                break;
        }
    }
    return state;
}
exports.getStateFromUrl = getStateFromUrl;
/**
 * Determines if the 2 url state are equal
 * @param a
 * @param b
 * @returns true if both states are equal. false otherwise
 *
 * @since 0.14.5
 */
function areStatesEqual(a, b) {
    return a.ft == b.ft
        && !(0, array_1.areArraysDifferent)(a.hg, b.hg) // We trust this is fast enough for the kinds of arrays we're expecting
        && !(0, array_1.areArraysDifferent)(a.hl, b.hl)
        && a.locale == b.locale
        && a.map == b.map
        && a.resource == b.resource
        && a.scale == b.scale
        && a.session == b.session
        && !(0, array_1.areArraysDifferent)(a.sg, b.sg)
        && !(0, array_1.areArraysDifferent)(a.sl, b.sl)
        && a.x == b.x
        && a.y == b.y;
}
exports.areStatesEqual = areStatesEqual;
//# sourceMappingURL=url-state.js.map