Source: jaws/RenderableJaw.js

import Jaw from "../Jaw";
import { Shark } from "../Shark";

/**
 * The base Class for View and Component classes. It implements method for template management.
 * 
 * @constructor
 * @param {string} jawId - 
 * @param {object} jawDefinition - An object with method to assign to this class. <strong>This parameter is deprecated and will be removed. Still exisists for back-compatibility reason.</strong>
 * 									<br>The <code>jawDefinition</code> parameter is deprecated and will be removed. Still exisists for back-compatibility reason.
 */
class RenderableJaw extends Jaw {
	constructor (jawId, jawDefinition) {
		super(jawId, jawDefinition);

		this.templateContent = "";
		this.type = "renderableJaw";

		this.__parsedTemplate = null;
		this.__parsedTemplates = null;
		this.__templates = {};
	}

	 _addTemplate (name, content) {
		//Devo gestire il caso in cui sia una View, che non può avere template multipli.
		if (name.trim() !== name || name.indexOf(" ") > -1) {
			console.error("Jaw.addTemplate: You can't have spaces in Template name.");
			return;
		}
		if (name.trim() === "__default__") {
			throw new Error("RenderableJaw.addTemplate: You can't use '__default__' as Template name, is a reserved name.");
			return;
		}

		if (name.trim() === "" || name === null) {
			if (this.templateContent === "") {
				this.templateContent = content;
				// this.templates["__default__"] = content;
				this.__templates["__default__"] = content;
			}
		}
		else {
			// this.templates[name] = content;
			this.__templates[name] = content;
		}

		return this.__templates;
	}

	/**
	 * Add an HTML template to this RenderableJaw.
	 *
	 * @returns {object} The complete list of Templates.
	 * @static
	 * @version 1.0.0, 2020.09.08
	 *
	 * @param {string} name - The name that will be used in container templates to print this template. If <code>null</code> or empty this will be the default template. There could be only one default template. Can be any string except "__default__" that is a reserved name.
	 * @param {string} content - The template HTML content.
	 */
	addTemplate (name, content) {
		return this._addTemplate(name, content);
	}

	parseTemplates () {
		// Dave: Uhm... devo parsare TUTTI i template

		if (!this.__templatesParsed) {

			for (let currTemplateName in this.__templates) {
				// Ecco, tutto il parsing deve stare qui
				this.__parsedTemplates[currTemplateName] = this.__templates[currTemplateName];
			}

			let templateContent = this.templateContent;

			// Vecchio giro per i componenti alla Mustache ------------------------------------------------------------------------
			let componentList = templateContent.match(/{{=>[\w\.]+\}\}/g);
			//	var componentTemplates = {};
			while (componentList) {
				componentList.forEach(function (item) {
					let processDefaultTemplate = true;
					let componentName = item.replace("{{=>", "").replace("}}", "");

					if (componentName.indexOf(".") > -1) {
						componentName = componentName.substr(0, componentName.indexOf("."));
						processDefaultTemplate = false;
					}

					let component = Shark.__components[componentName];

					if (component) {
						if (processDefaultTemplate) {
							templateContent = templateContent.replace(item, component.__parsedTemplate || component.templateContent);
						}

						if (component.__templates) {
							for (let currTemplateName in component.__templates) {
								templateContent = templateContent.replace(`{{=>${componentName}.${currTemplateName}}}`, component.__parsedTemplates[templateName] || component.__templates[currTemplateName]);
							}
						}
					}
					else {
						Shark.trace("PreactRenderer.render > Missing component: " + componentName, Shark.TRACE_ERROR);
						templateContent = templateContent.replace(item, item.replace("{{=>", "{{>"));
					}
				});

				componentList = templateContent.match(/{{=>[\w\.]+\}\}/g);
			}

			//------------------------------------------------------------------------

			// Nuovo giro per i componenti tipo <shark- ------------------------------------------------------------------------
			let customHtmlComponentRegEx = new RegExp(/<shark-[\w]+.+\/*>/g);
			let customHtmlComponentList = templateContent.match(customHtmlComponentRegEx);

			while (customHtmlComponentList) {
				customHtmlComponentList.forEach(function (item) {
					let componentName = item;
					let templateName = "";

					//Dave: qui devo controllare anche se esiste senza "Component" alla fine
					if (componentName.indexOf("></shark-") > -1) {
						componentName = componentName.substr(0, componentName.indexOf("></shark-"));
					}
					if (componentName.indexOf("/>") > -1) {
						componentName = componentName.substr(0, componentName.indexOf("/>"));
					}
					if (componentName.indexOf(">") > -1) {
						componentName = componentName.substr(0, componentName.indexOf(">"));
					}
					if (componentName.indexOf(" ") > -1) {
						componentName = componentName.substr(0, componentName.indexOf(" "));
					}
					componentName = componentName.replace("<shark-", "");

					if (componentName.indexOf("-") > -1) {
						componentName = Utils.dashedToCamel(componentName);
					}

					let templateAttrStart = item.indexOf("template=\"");
					if (templateAttrStart > -1) {
						templateName = item.substring(templateAttrStart + 10, item.indexOf("\"", templateAttrStart + 11));

						if (templateName === "default") {
							templateName = "";
						}
					}

					let component = Shark.__components[componentName];
					if (component) {
						if (templateName === "") {
							templateContent = templateContent.replace(item, component.__parsedTemplate || component.templateContent);
						}
						else {
							if (component.__templates && component.__templates[templateName]) {
								templateContent = templateContent.replace(item, component.__parsedTemplates[templateName] || component.__templates[templateName]);
							}
						}
					}
					else {
						Shark.trace("RenderableJaw.parseTemplate > Missing component: " + componentName + ", removing from template.", Shark.TRACE_ERROR);
						templateContent = templateContent.replace(item, "");
					}
				});

				customHtmlComponentList = templateContent.match(customHtmlComponentRegEx);
			}
			//------------------------------------------------------------------------
			templateContent = templateContent.replace(/data-sh-model=\"(.\S+)\"/g, `$& data-shguid="{{$1.__shguid}}"`);
			
			templateContent = templateContent.replace(/\t/g, "");
			//Dave: probabilmente questo serve solo per VirtualDOMRenderer
			// templateContent = templateContent.replace(/<br[\s\S\ ]*?(?=>)/g, "$&/");
			// templateContent = templateContent.replace(/<hr[\s\S\ ]*?(?=>)/g, "$&/");
			// templateContent = templateContent.replace(/<img [\s\S\ ]*?(?=>)/g, "$&/");
			// templateContent = templateContent.replace(/<input [\s\S\ ]*?(?=>)/g, "$&/");

			this.__parsedTemplate = templateContent;
			this.__templatesParsed = true;
	   }
	}

	/**
	 * Set the default HTML template to this RenderableJaw.
	 *
	 * @returns {object} The complete list of Templates.
	 * @static
	 * @version 1.0.0, 2020.12.03
	 *
	 * @param {string} content - The template HTML content.
	 */
	setTemplate (content) {
		return this._addTemplate("", content);
	}
}

export default RenderableJaw;