/**
 * 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 {
	isArray,
	isBoolean,
	isFunction,
	isInstance,
	isInteger,
	isIterable,
	isObject,
	isPrimitive,
	isString,
	isSymbol,
} from "./is.mjs";

export {
	validateIterable,
	validatePrimitive,
	validateBoolean,
	validateString,
	validateObject,
	validateInstance,
	validateArray,
	validateSymbol,
	validateFunction,
	validateInteger,
};

/**
 * This method checks if the type matches the primitive type. this function is identical to isPrimitive() except that a TypeError is thrown.
 *
 * ```
 * <script type="module">
 * import {validateIterable} from '@schukai/monster/source/types/validate.mjs';
 * console.log(validateIterable('2'))  // ↦ TypeError
 * console.log(validateIterable([]))  // ↦ value
 * </script>
 * ```
 *
 * @param {*} value
 * @return {*}
 * @license AGPLv3
 * @since 1.2.0
 * @copyright Volker Schukai
 * @throws {TypeError} value is not a primitive
 * @see {@link isPrimitive}
 * @see {@link Monster.Types.isPrimitive}
 * @see {@link Monster.Types#isPrimitive}
 */
function validateIterable(value) {
	if (!isIterable(value)) {
		throw new TypeError("value is not iterable");
	}
	return value;
}

/**
 * This method checks if the type matches the primitive type. this function is identical to isPrimitive() except that a TypeError is thrown.
 *
 * ```
 * <script type="module">
 * import {validatePrimitive} from '@schukai/monster/source/types/validate.mjs';
 * console.log(validatePrimitive('2'))  // ↦ value
 * console.log(validatePrimitive([]))  // ↦ TypeError
 * </script>
 * ```
 *
 * @param {*} value
 * @return {*}
 * @license AGPLv3
 * @since 1.0.0
 * @copyright Volker Schukai
 * @throws {TypeError} value is not a primitive
 * @see {@link isPrimitive}
 * @see {@link Monster.Types.isPrimitive}
 * @see {@link Monster.Types#isPrimitive}
 */
function validatePrimitive(value) {
	if (!isPrimitive(value)) {
		throw new TypeError("value is not a primitive");
	}
	return value;
}

/**
 * This method checks if the type matches the boolean type. this function is identical to isBoolean() except that a TypeError is thrown.
 *
 * ```
 * <script type="module">
 * import {validateBoolean} from '@schukai/monster/source/types/validate.mjs';
 * console.log(validateBoolean(false))  // ↦ value
 * console.log(validateBoolean('2'))  // ↦ TypeError
 * console.log(validateBoolean([]))  // ↦ TypeError
 * </script>
 * ```
 *
 * @param {*} value
 * @return {*}
 * @license AGPLv3
 * @since 1.0.0
 * @copyright Volker Schukai

 * @throws {TypeError}  value is not primitive
 */
function validateBoolean(value) {
	if (!isBoolean(value)) {
		throw new TypeError("value is not a boolean");
	}
	return value;
}

/**
 * This method checks if the type matches the string type. this function is identical to isString() except that a TypeError is thrown.
 *
 * ```
 * <script type="module">
 * import {validateString} from '@schukai/monster/source/types/validate.mjs';
 * console.log(validateString('2'))  // ↦ value
 * console.log(validateString([]))  // ↦ TypeError
 * </script>
 * ```
 *
 * @param {*} value
 * @return {*}
 * @license AGPLv3
 * @since 1.0.0
 * @copyright Volker Schukai
 * @throws {TypeError} value is not a string
 */
function validateString(value) {
	if (!isString(value)) {
		throw new TypeError("value is not a string");
	}
	return value;
}

/**
 * This method checks if the type matches the object type. this function is identical to isObject() except that a TypeError is thrown.
 *
 * ```
 * <script type="module">
 * import {validateObject} from '@schukai/monster/source/types/validate.mjs';
 * console.log(validateObject({}))  // ↦ value
 * console.log(validateObject('2'))  // ↦ TypeError
 * console.log(validateObject([]))  // ↦ TypeError
 * </script>
 * ```
 *
 * @param {*} value
 * @return {*}
 * @license AGPLv3
 * @since 1.0.0
 * @copyright Volker Schukai
 * @throws {TypeError} value is not a object
 */
function validateObject(value) {
	if (!isObject(value)) {
		throw new TypeError("value is not a object");
	}
	return value;
}

/**
 * This method checks if the type matches the object instance.
 *
 * ```
 * <script type="module">
 * import {validateInstance} from '@schukai/monster/source/types/validate.mjs';
 * console.log(validateInstance({}, Object)) // ↦ value
 * console.log(validateInstance('2', Object)) // ↦ TypeError
 * console.log(validateInstance([], Object)) // ↦ TypeError
 * </script>
 * ```
 *
 * @param {*} value
 * @param {object} instance
 * @return {*}
 * @license AGPLv3
 * @since 1.5.0
 * @copyright Volker Schukai
 * @throws {TypeError} value is not an instance of
 */
function validateInstance(value, instance) {
	if (!isInstance(value, instance)) {
		let n = "";
		if (isObject(instance) || isFunction(instance)) {
			n = instance?.["name"];
		}

		if (n) {
			n = ` ${n}`;
		}

		throw new TypeError(`value is not an instance of${n}`);
	}
	return value;
}

/**
 * This method checks if the type matches the array type. this function is identical to isArray() except that a TypeError is thrown.
 *
 * ```
 * <script type="module">
 * import {validateArray} from '@schukai/monster/source/types/validate.mjs';
 * console.log(validateArray('2'))  // ↦ TypeError
 * console.log(validateArray([]))  // ↦ value
 * </script>
 * ```
 *
 * @param {*} value
 * @return {*}
 * @license AGPLv3
 * @since 1.0.0
 * @copyright Volker Schukai
 * @throws {TypeError} value is not an array
 */
function validateArray(value) {
	if (!isArray(value)) {
		throw new TypeError("value is not an array");
	}
	return value;
}

/**
 * This method checks if the type matches the symbol type. this function is identical to isSymbol() except that a TypeError is thrown.
 *
 * ```
 * <script type="module">
 * import {validateSymbol} from '@schukai/monster/source/types/validate.mjs';
 * console.log(validateSymbol('2'))  // ↦ TypeError
 * console.log(validateSymbol())  // ↦ value
 * </script>
 * ```
 *
 * @param {*} value
 * @return {*}
 * @license AGPLv3
 * @since 1.9.0
 * @copyright Volker Schukai
 * @throws {TypeError} value is not an symbol
 */
function validateSymbol(value) {
	if (!isSymbol(value)) {
		throw new TypeError("value is not an symbol");
	}
	return value;
}

/**
 * This method checks if the type matches the function type. this function is identical to isFunction() except that a TypeError is thrown.
 *
 * ```
 * <script type="module">
 * import {validateFunction} from '@schukai/monster/source/types/validate.mjs';
 * console.log(validateFunction(()=>{})) // ↦ value
 * console.log(validateFunction('2'))  // ↦ TypeError
 * console.log(validateFunction([]))  // ↦ TypeError
 * </script>
 * ```
 *
 * @param {*} value
 * @return {*}
 * @license AGPLv3
 * @since 1.0.0
 * @copyright Volker Schukai
 * @throws {TypeError} value is not a function
 */
function validateFunction(value) {
	if (!isFunction(value)) {
		throw new TypeError("value is not a function");
	}
	return value;
}

/**
 * This method checks if the type is an integer. this function is identical to isInteger() except that a TypeError is thrown.
 *
 * ```
 * <script type="module">
 * import {validateFunction} from '@schukai/monster/source/types/validate.mjs';
 * console.log(validateInteger(true)) // ↦ TypeError
 * console.log(validateInteger('2'))  // ↦ TypeError
 * console.log(validateInteger(2))  // ↦ value
 * </script>
 * ```
 *
 * @param {*} value
 * @return {*}
 * @license AGPLv3
 * @since 1.4.0
 * @copyright Volker Schukai
 * @throws {TypeError} value is not an integer
 */
function validateInteger(value) {
	if (!isInteger(value)) {
		throw new TypeError("value is not an integer");
	}
	return value;
}
