/**
 * Copyright © Volker Schukai and all contributing authors, {{copyRightYear}}. All rights reserved.
 * Node module: @schukai/monster
 *
 * This source code is licensed under the GNU Affero General Public License version 3 (AGPLv3).
 * The full text of the license can be found at: https://www.gnu.org/licenses/agpl-3.0.en.html
 *
 * For those who do not wish to adhere to the AGPLv3, a commercial license is available.
 * Acquiring a commercial license allows you to use this software without complying with the AGPLv3 terms.
 * For more information about purchasing a commercial license, please contact Volker Schukai.
 *
 * SPDX-License-Identifier: AGPL-3.0
 */

import { getWindow } from "../../dom/util.mjs";
import { isString } from "../../types/is.mjs";

export {
	generateConfigKey,
	generateComponentConfigKey,
	generateUniqueConfigKey,
	sanitizeConfigKey,
};

/**
 * Generate a unique configuration key based on the current browser location,
 * component name, id, and a prefix.
 *
 * @since 3.55.0 the function remove the hash from the key
 *
 * @param {string} componentName - The name of the component.
 * @param {string} id - A unique identifier for the component.
 * @param {string} prefix - A prefix to use in the unique key.
 * @return {string} The generated unique configuration key.
 */
function generateUniqueConfigKey(componentName, id, prefix) {
	// Get the browser location without parameters
	const urlWithoutParams = getWindow().location.href.split("?")[0];

	// Without hash (since 3.55.0)
	const urlWithoutParamsAndHash = urlWithoutParams.split("#")[0];

	// Combine the parts to create a unique key
	const uniqueKey = `${prefix}_${urlWithoutParamsAndHash}_${componentName}_${id}`;

	// Replace any special characters and spaces with underscores
	return sanitizeConfigKey(uniqueKey);
}

/**
 * Generate a stable host configuration key from an explicit technical instance key.
 *
 * @param {string} componentName - The name of the component.
 * @param {string} instanceKey - Technical, host-defined instance key.
 * @param {string} scope - Configuration scope, for example "filter".
 * @return {string}
 */
function generateConfigKey(componentName, instanceKey, scope) {
	return sanitizeConfigKey(`${scope}_${componentName}_${instanceKey}`);
}

/**
 * Generate a component host configuration key.
 *
 * If an explicit instance key is provided, the key is independent from the
 * current URL and DOM id. Without an instance key, this keeps the historical
 * URL-derived key for backwards compatibility.
 *
 * @param {string} componentName
 * @param {string} id
 * @param {string} scope
 * @param {object} [options]
 * @param {string} [options.instanceKey]
 * @return {string}
 */
function generateComponentConfigKey(componentName, id, scope, options = {}) {
	if (isString(options.instanceKey) && options.instanceKey.trim() !== "") {
		return generateConfigKey(componentName, options.instanceKey.trim(), scope);
	}

	return generateUniqueConfigKey(componentName, id, scope);
}

/**
 * @param {string} key
 * @return {string}
 */
function sanitizeConfigKey(key) {
	return String(key)
		.replace(/[^\w\s]/gi, "_")
		.replace(/\s+/g, "_");
}
