/**
 * 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 { internalSymbol } from "../constants.mjs";
import { extend } from "../data/extend.mjs";
import { Pathfinder } from "../data/pathfinder.mjs";
import { Base } from "./base.mjs";
import { validateObject } from "./validate.mjs";
import { isObject } from "./is.mjs";

export { BaseWithOptions };

/**
 * This is the base class with options from which some monster classes are derived.
 *
 * This class is actually only used as a base class.
 *
 * Classes that require the possibility of options can be derived directly from this class.
 * Derived classes almost always override the `default` getter with their own values.
 *
 * This class is deprecated since 3.15.0. Use `BaseWithDefaults` instead.
 *
 * @license AGPLv3
 * @since 1.13.0
 * @copyright Volker Schukai
 * @deprecated since 3.15.0
 */
class BaseWithOptions extends Base {
	/**
	 *
	 * @param {object} options
	 */
	constructor(options) {
		super();

		if (!isObject(options)) {
			options = {};
		}

		this[internalSymbol] = extend({}, this.defaults, validateObject(options));
	}

	/**
	 * This getter provides the options. Derived classes overwrite
	 * this getter with their own values. It is a good karma to always include
	 * the values from the parent class.
	 *
	 * ```javascript
	 * get defaults() {
	 *     return Object.assign({}, super.defaults, {
	 *         mykey: true
	 *     });
	 * }
	 *
	 * ```
	 *
	 * @return {object}
	 */
	get defaults() {
		return {};
	}

	/**
	 * nested options can be specified by path `a.b.c`
	 *
	 * @param {string} path
	 * @param {*} defaultValue
	 * @return {*}
	 * @since 1.10.0
	 */
	getOption(path, defaultValue) {
		let value;

		try {
			value = new Pathfinder(this[internalSymbol]).getVia(path);
		} catch (e) {}

		if (value === undefined) return defaultValue;
		return value;
	}
}
