package com.utopiaindustries.util;

import com.utopiaindustries.dialect.CTPDialect;
import org.springframework.stereotype.Component;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
import org.w3c.tidy.Tidy;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.Map;

@Component
public class HTMLBuilder {
    private final String UTF_8 = StandardCharsets.UTF_8.displayName();

    public String buildHTML( String templateName, Model model ) throws Exception {
        // template resolver
        ClassLoaderTemplateResolver pdfTemplateResolver = createPDFTemplateResolver();
        // template engine
        TemplateEngine templateEngine = new TemplateEngine();
        templateEngine.setTemplateResolver( pdfTemplateResolver );
        templateEngine.addDialect( new CTPDialect() );
        // context
        Context ctx = configureContext( model );
        // render the template
        String renderedHTMLContent = templateEngine.process( templateName, ctx );
        return convertToXhtml( renderedHTMLContent );
    }

    public String buildHTMLMap( String templateName, ModelMap model ) throws Exception {
        // template resolver
        ClassLoaderTemplateResolver pdfTemplateResolver = createPDFTemplateResolver();
        // template engine
        TemplateEngine templateEngine = new TemplateEngine();
        templateEngine.setTemplateResolver( pdfTemplateResolver );
        templateEngine.addDialect( new CTPDialect() );
        // context
        Context ctx = configureContextMap( model );
        // render the template
        String renderedHTMLContent = templateEngine.process( templateName, ctx );
        return convertToXhtml( renderedHTMLContent );
    }

    private String convertToXhtml( String html ) throws UnsupportedEncodingException {
        Tidy tidy = new Tidy();
        tidy.setInputEncoding( UTF_8 );
        tidy.setOutputEncoding( UTF_8 );
        tidy.setXHTML( true );
        ByteArrayInputStream inputStream = new ByteArrayInputStream( html.getBytes( UTF_8 ) );
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        tidy.parseDOM( inputStream, outputStream );
        return outputStream.toString( UTF_8 );
    }

    private ClassLoaderTemplateResolver createPDFTemplateResolver() {
        ClassLoaderTemplateResolver pdfTemplateResolver = new ClassLoaderTemplateResolver();
        pdfTemplateResolver.setPrefix( "/templates/" );
        pdfTemplateResolver.setTemplateMode( TemplateMode.HTML );
        pdfTemplateResolver.setSuffix( ".html" );
        pdfTemplateResolver.setCharacterEncoding( UTF_8 );
        pdfTemplateResolver.setOrder( 1 );
        return pdfTemplateResolver;
    }

    private Context configureContext( Model model ) {
        Context ctx = new Context();
        // adding model attributes to context
        for ( Map.Entry<String, Object> entry: model.asMap().entrySet() ) {
            ctx.setVariable( entry.getKey(), entry.getValue() );
        }
        return ctx;
    }

    private Context configureContextMap( ModelMap model ) {
        Context ctx = new Context();
        // adding model attributes to context
        for ( Map.Entry<String, Object> entry: model.entrySet() ) {
            ctx.setVariable( entry.getKey(), entry.getValue() );
        }
        return ctx;
    }
}

