package com.tlswe.awsmock.common.util;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.tlswe.awsmock.common.exception.AwsMockException;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

/**
 * Utilities that writes/gets string output from FreeMarker (http://freemarker.org/) templates.
 *
 * @author xma
 *
 */
public final class TemplateUtils {

    /**
     * Log writer for this class.
     */
    private static Logger log = LoggerFactory.getLogger(TemplateUtils.class);

    /**
     * Global configuration for FreeMarker.
     */
    private static Configuration conf = new Configuration();

    /**
     * Path for the folder relative to this class under which we store and load the freemarker templates.
     */
    private static final String PATH_FOR_TEMPLATES = "/templates";

    // tell FreeMarker where to load templates - from folder "templates", in
    // classpath
    static {
        conf.setClassForTemplateLoading(TemplateUtils.class, PATH_FOR_TEMPLATES);
    }


    /**
     * Constructor is made private as this is a utility class which should be always used in static way.
     */
    private TemplateUtils() {

    }


    /**
     * Generate result from given template and data and print to writer.
     *
     * @param templateFilename
     *            filename of the .ftl file
     * @param data
     *            data to fill in the template, as key-values
     * @param writer
     *            target writer to print the result
     */
    public static void write(final String templateFilename, final Map<String, Object> data, final Writer writer)
    {

        Template tmpl = null;
        try {
            // note that we don't need to cache templates by ourselves since
            // getTemplate() does that internally already
            tmpl = conf.getTemplate(templateFilename);
        } catch (FileNotFoundException e1) {
            String errMsg = "FileNotFoundException: template file '" + templateFilename + "' not found";
            log.error("{}: {}", errMsg, e1.getMessage());
            throw new AwsMockException(errMsg, e1);
        } catch (IOException e) {
            String errMsg = "IOException: failed to getTemplate (filename is " + templateFilename + ")";
            log.error("{}: {}", errMsg, e.getMessage());
            throw new AwsMockException(errMsg, e);
        }

        try {
            tmpl.process(data, writer);
        } catch (TemplateException e) {
            StringBuilder dataDescription = new StringBuilder();

            if (null != data) {
                for (Map.Entry<String, Object> entry : data.entrySet()) {
                    dataDescription.append(entry.getKey() + " - " + entry.getValue()).append('\n');
                }
            }
            String errMsg = "TemplateException: failed to process template '" + templateFilename + "', with data: "
                    + dataDescription.toString()
                    + " The probable cause could be un-matching of key-values for that template. ";
            log.error("{}: {}", errMsg, e.getMessage());
            throw new AwsMockException(errMsg, e);
        } catch (IOException e) {
            String errMsg = "IOException: failed to process template and write to writer. ";
            log.error("{}: {}", errMsg, e.getMessage());
            throw new AwsMockException(errMsg, e);
        }

    }


    /**
     * Generate result from given template and data and get it as a string.
     *
     * @param templateName
     *            filename of the .ftl file
     * @param data
     *            data to fill in the template, as key-values
     * @return processed result from template and data
     */
    public static String get(final String templateName, final Map<String, Object> data) {
        StringWriter writer = new StringWriter();
        write(templateName, data, writer);
        return writer.toString();
    }

}

@@ -518,16 +518,368 @@
 mplates.
+ All templates are%0A * located under a folder named %22templates%22 in the root folder which is relative to where this class is in the%0A * classpath. In case of any errors during processing such as %7B@link TemplateException%7D or %7B@link FileNotFoundException%7D%0A * (missing template), an %7B@link AwsMockException%7D wrapping the original exception will be raised.%0A *
 %0A *%0A * @
@@ -1745,36 +1745,28 @@
 %0A     * 
-Generate result from
+Process with
  given t
@@ -1765,35 +1765,33 @@
  given template 
-and
++
  data and print 
@@ -1784,20 +1784,30 @@
 ata and 
-prin
+then put resul
 t to wri
@@ -1955,32 +1955,41 @@
 he template, as 
+pairs of 
 key-values%0A     
@@ -2180,16 +2180,11 @@
 ter)
-%0A   
  %7B%0A
-%0A
     
@@ -2236,17 +2236,33 @@
        /
-/
+*-%0A             *
  note th
@@ -2319,23 +2319,8 @@
 ince
-%0A            //
  get
@@ -2359,16 +2359,32 @@
 already%0A
+             */%0A
         
@@ -3992,28 +3992,20 @@
   * 
-Generate result from
+Process with
  giv
@@ -4012,27 +4012,25 @@
 en template 
-and
++
  data and ge
@@ -4031,17 +4031,21 @@
 and get 
-i
+resul
 t as a s
@@ -4199,16 +4199,25 @@
 ate, as 
+pairs of 
 key-valu

Add more explaination to javadoc for TemplateUtils.java