/**
 * 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 {
	CustomElement,
	assembleMethodSymbol,
} from "../../dom/customelement.mjs";
import { diff } from "../../data/diff.mjs";
import { Datasource as DatasourceBase } from "../../data/datasource.mjs";
import { instanceSymbol } from "../../constants.mjs";

export { Datasource, dataSourceSymbol };

/**
 * @private
 * @type {symbol}
 */
const dataSourceSymbol = Symbol.for(
	"@schukai/monster/components/datasource@@datasource",
);

/**
 * A datasource
 *
 * @fragments /fragments/components/datatable/datasource
 *
 * @example /examples/components/datatable/datasource
 *
 * @issue https://localhost.alvine.dev:8440/development/issues/closed/272.html
 *
 * @copyright Volker Schukai
 * @summary A generic datasource bridge for connecting datatables and controls to structured data providers.
 */
class Datasource extends CustomElement {
	/**
	 * the constructor of the class
	 */
	constructor() {
		super();
		this[dataSourceSymbol] = new DatasourceBase();
	}

	/**
	 * This method is called by the `instanceof` operator.
	 * @return {symbol}
	 */
	static get [instanceSymbol]() {
		return Symbol.for("@schukai/monster/components/datasource@@instance");
	}

	/**
	 * To set the options via the HTML tag, the attribute `data-monster-options` must be used.
	 * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
	 *
	 * The individual configuration values can be found in the table.
	 *
	 * @property {Object} templates Template definitions
	 * @property {string} templates.main Main template
	 */
	get defaults() {
		return Object.assign({}, super.defaults, {
			logLevel: "error",
			features: {
				// Feature flag: default-on no-op event suppression, can be rolled back.
				skipNoopEvents: true,
			},
		});
	}

	/**
	 * @return {void}
	 */
	[assembleMethodSymbol]() {
		super[assembleMethodSymbol]();
	}

	/**
	 * Get the data, without proxy
	 * @return {Object}
	 */
	get data() {
		return this[dataSourceSymbol].get();
	}

	/**
	 * set the data with proxy
	 * @param {Object} data
	 */
	set data(data) {
		if (this.getOption("logLevel") === "debug") {
			console.log("monster-datasource: set data", {
				data: data,
			});
		}
		if (this.getOption("features.skipNoopEvents") === true) {
			const current = this[dataSourceSymbol].get();
			if (diff(current, data).length === 0) {
				return;
			}
		}
		this[dataSourceSymbol].set(data);
	}

	/**
	 * Get the base datasource
	 * @return {Datasource}
	 */
	get datasource() {
		return this[dataSourceSymbol];
	}

	/**
	 * Wrapper for the write method of the datasource
	 */
	write() {
		this[dataSourceSymbol].write();
	}

	/**
	 * Wrapper for the read method of the datasource
	 */
	read() {
		this[dataSourceSymbol].read();
	}
}
