import React, { useMemo } from "react";
import { useSelector, } from "react-redux";
import { InputOqt, processOptions, reactorParser, useHtmlParser } from "../..";
import { TagWithVariable } from "./";
import { ReactorLink, GeolocationOqt } from "../";
import { InputCheckBoxOqt } from "../input";
import { components, regexp, makeComponent, anyReplaceAttribs, resolveAttribs, anyVariableAttribs, matchText, resolverItem, getTypes } from "./Template.helpers";
import { useEffect } from "react";
const objectPath = require("object-path");
/**
* Componente que renderiza un objeto llamando a un template en memoria o un string como html.
* @name Reactor.Components.Templates.Template
* @param {Object|string} content Contenido que va a renderizarse
* @class
* @example
<template content='{"template":"NombreDeTemplate", "titulo": "{{titulo}}"}' />
*/
export const Template = ({content}) => {
const { parse, domToReact } = useHtmlParser();
const templates = useSelector(state => state.app.templates);
const contentType = useMemo(() => typeof content, [content]);
const noTemplate = useMemo(() => !templates || templates.length === 0, [templates]);
const template = useMemo(()=>{
let template;
if (!noTemplate && (content && content.template && typeof content.template === "string")){
template = templates[content.template.toLowerCase()];
}else if(content){
template = {body: content.template};
}
return template;
}, [noTemplate, templates, content]);
const options = useMemo(()=>({
replace: ({children, attribs, name, data, ...params}) => {
if(params.type === "tag" && name === "a"){
//const attributes = anyReplaceAttribs(attribs) ? resolveAttribs(attribs, content) : attribs;
const attributes = anyReplaceAttribs(attribs) ? resolveAttribs(attribs, content) : attribs;
if(anyVariableAttribs(attribs)){
return makeComponent(TagWithVariable, {...resolveAttribs(attribs, content), title: attributes.title, tag: ReactorLink, children: children && domToReact(children, options)})
}else{
return makeComponent(ReactorLink, {...attributes, children: children && domToReact(children, options)})
}
}
if(params.type === "tag" && name==="option"){
const attributes = anyReplaceAttribs(attribs) ? resolveAttribs(attribs, content, false) : attribs;
//console.log({attribs, attributes})
return <option {...attributes}>{matchText(children[0].data, content)}</option>;
}
if(params.type === "tag" && name==="textarea"){
const attributes = anyReplaceAttribs(attribs) ? resolveAttribs(attribs, content, false) : attribs;
return <textarea {...attributes}>{children[0] && matchText(children[0].data, content) || ""}</textarea>;
}
if(params.type === "tag" && (name === "for_each" || name === "live")){
const Component = components[name]();
if(anyVariableAttribs(attribs)){
return makeComponent(TagWithVariable, {...resolveAttribs(attribs, content), tag: Component, children: children && domToReact(children, options)})
}else{
const attributes = anyReplaceAttribs(attribs) ? resolveAttribs(attribs, content) : attribs;
return makeComponent(Component, {...attributes, template: attributes.template && attributes.template.replace("[[", "{{").replace("]]", "}}"), children: children && domToReact(children, options)})
}
}
if(params.type === "tag"){
if( components[name] ){
const Component = components[name]();
if(anyVariableAttribs(attribs)){
return makeComponent(TagWithVariable, {...resolveAttribs(attribs, content), tag: Component, children: children && domToReact(children, options)})
}else{
const attributes = anyReplaceAttribs(attribs) ? resolveAttribs(attribs, content) : attribs;
return makeComponent(Component, {...attributes, children: children && domToReact(children, options)})
}
}
}
if(params.type === "tag" && name === "img" && anyReplaceAttribs(attribs)){
const attributes = resolveAttribs(attribs, content);
return <img {...attributes} />;
}
if(params.type === "tag" && name === "geolocation" ){
const attributes = resolveAttribs(attribs, content);
return <GeolocationOqt {...attributes}>{domToReact(children, options)}</GeolocationOqt>;
}
if(params.type === "tag" && name === "input" && anyReplaceAttribs(attribs)){
const attributes = resolveAttribs(attribs, content);
//return attributes.type === "checkbox" ? <InputCheckBoxOqt {...attributes} /> : <InputOqt {...attributes} />;
if(anyVariableAttribs(attribs)){
return makeComponent(TagWithVariable, {...attributes, tag: attributes.type === "checkbox" ? InputCheckBoxOqt : InputOqt, children: undefined})
}else{
return makeComponent(attributes.type === "checkbox" ? InputCheckBoxOqt : InputOqt, {...attributes, children: undefined})
}
}
if(params.type === "tag" && anyReplaceAttribs(attribs)){
const attributes = resolveAttribs(attribs, content);
const Tag = name;
if(anyVariableAttribs(attribs)){
return makeComponent(TagWithVariable, {...attributes, tag: Tag, children: children && domToReact(children, options)})
}else{
return makeComponent(Tag, {...attributes, children: children && domToReact(children, options)})
}
}
if(params.type === "tag" && name === "object"){
const attributes = resolveAttribs(attribs, content);
const Tag2 = attributes.tag;
const newOptions = attributes.options ? JSON.parse(attributes.options, reactorParser) : {};
return <Tag2 {...newOptions}>{domToReact(children, options)}</Tag2>;
}
// Función para procesar el template y generar el JSX
if(params.type === "text"){
//return generarJSX(data, content)
const matches = data.match(regexp);
//console.log({params, data, matches})
if(matches){
return (
<>
{
matches
.map(x => x.replace("{{", "").replace("}}", ""))
.map( match => {
const [ splitMatch, defaultTemplate] = match.split("|");
const targetContent = content;
const childContent = objectPath.get(targetContent, `${splitMatch}`.trim());
//console.log("resolverItem", {childContent, defaultTemplate})
return resolverItem(childContent, defaultTemplate);
})
}
</>
);
}
}
}
}), [content]);
const types = useMemo(() => getTypes(options, template, parse), [options, template]);
const result = useMemo(() => {
return noTemplate
? <></>
: (types[contentType] ? types[contentType](content) : types.default(content));
}, [noTemplate, contentType, types, content]);
return result;
}
const generarJSX = (template, content) => {
const partes = template.split(/({{[^{}]+}})/g);
const jsx = partes.map((parte, index) => {
if (parte.match(/({{[^{}]+}})/)) {
const clave = parte.slice(2, -2);
const [ data, defaultTemplate ] = clave.split("|");
const dataProcess = processOptions(data.trim(), "", data);
if(typeof dataProcess === "string"){
console.log("string", dataProcess)
return resolverItem(objectPath.get(content, dataProcess), defaultTemplate);
}else if(typeof dataProcess === "object"){
console.log("object", dataProcess)
return resolverItem({...dataProcess, template: defaultTemplate});
}
console.log("otra cosa", dataProcess)
//const clave = parte.slice(2, -2);
//return <span key={index}>{datos[clave]}</span>;
} else {
//console.log(parte)
return parte;
}
});
//console.log(jsx);
return jsx;
}