package com.github.onsdigital.babbage.template;

import com.github.onsdigital.babbage.template.handlebars.HandlebarsRenderer;
import com.github.onsdigital.babbage.util.ThreadContext;
import org.apache.commons.lang3.ArrayUtils;

import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.Map;

import static com.github.onsdigital.babbage.configuration.ApplicationConfiguration.appConfig;
import static com.github.onsdigital.babbage.util.json.JsonUtil.toMap;

/**
 * Created by bren on 28/05/15. Resolves data type and renders html page.
 * <p/>
 * Template service includes current {@link com.github.onsdigital.babbage.util.ThreadContext} in the context with key value names
 */
public class TemplateService {

    private static TemplateService instance = new TemplateService();

    private static HandlebarsRenderer renderer = new HandlebarsRenderer(appConfig().handlebars().getTemplatesDirectory(),
            appConfig().handlebars().getTemplatesSuffix(), appConfig().handlebars().isReloadTemplateChanges());

    private TemplateService() {
    }

    public static TemplateService getInstance() {
        return instance;
    }

    /**
     * Renders data using main template, current ThreadContext data is added to context as additional data
     *
     * @param data           Main data to render template with
     * @param additionalData optional additional data map, map keys will be set as the object name when combined with main data
     * @return
     * @throws IOException
     */
    public String renderContent(Object data, Map<String, Object>... additionalData) throws IOException {
        return renderer.render(appConfig().handlebars().getMainContentTemplateName(), sanitize(data), addThreadContext(additionalData));
    }

    /**
     * Renders chart configuration using main chart configuration template, current ThreadContext data is added to context as additional data
     *
     * @param data           Main data to render template with
     * @param additionalData optional additional data map, map keys will be set as the object name when combined with main data
     * @return
     * @throws IOException
     */
    public String renderChartConfiguration(Object data, Map<String, Object>... additionalData) throws IOException {
        return renderer.render(appConfig().handlebars().getMainChartConfigTemplateName(), sanitize(data), addThreadContext(additionalData));
    }

    /**
     * Renders template with no data other than current thread context
     *
     * @param templateName
     * @return
     * @throws IOException
     */
    public String renderTemplate(String templateName) throws IOException {
        return renderer.render(templateName, Collections.emptyMap(), ThreadContext.getAllData());
    }

    /**
     * Renders template with given name using given data, current ThreadContext data is added to context as additional data
     *
     * @param templateName
     * @param data
     * @param additionalData optional additional data
     * @return
     * @throws IOException
     */
    public String renderTemplate(String templateName, Object data, Map<String, Object>... additionalData) throws IOException {
        return renderer.render(templateName, sanitize(data), addThreadContext(additionalData));
    }

    /*Converts object into map if json string or json input stream*/
    public static Object sanitize(Object data) throws IOException {
        if (data instanceof String) {
            return toMap((String) data);
        } else if (data instanceof InputStream) {
            return toMap((InputStream) data);
        } else {
            return data;
        }
    }

    /**
     * Add current thread context to map array
     *
     * @param data
     * @return
     */
    private Map<String, Object>[] addThreadContext(Map<String, Object>... data) {
        return ArrayUtils.add(data, ThreadContext.getAllData());
    }

}

@@ -1165,32 +1165,37 @@
 nstance;%0A    %7D%0A%0A
+    %0A
     /**%0A     * R
@@ -1363,37 +1363,291 @@
 te with%0A     * @
-param
+return%0A     * @throws IOException%0A     */%0A    public String renderContent(Object data) throws IOException %7B%0A        return renderContent(data, null);%0A    %7D%0A    %0A    /**%0A     * Renders data using main template, current ThreadContext data is added to context as
  additionalData 
@@ -1637,37 +1637,128 @@
 s additional
-Data op
+ data%0A     *%0A     * @param data           Main data to render template with%0A     * @param addi
 tional
+Data
  additional 
@@ -1942,35 +1942,32 @@
 %3CString, Object%3E
-...
  additionalData)
@@ -2377,33 +2377,24 @@
 itionalData 
-optional 
 additional d
@@ -2588,35 +2588,32 @@
 %3CString, Object%3E
-...
  additionalData)
@@ -3037,33 +3037,32 @@
 eturn render
-er.render
+Template
 (templateNam
@@ -3086,16 +3086,338 @@
 ptyMap()
+);%0A    %7D%0A%0A    /**%0A     * Renders template with given name using given data and current thread context%0A     *%0A     * @param templateName%0A     * @return%0A     * @throws IOException%0A     */%0A    public String renderTemplate(String templateName, Object data) throws IOException %7B%0A        return renderTemplate(templateName, data
 , Thread
@@ -3664,17 +3664,8 @@
 ata 
-optional 
 addi
@@ -3812,19 +3812,16 @@
  Object%3E
-...
  additio

Remove varargs param