package com.udapsoft.modular.web.template;

import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Map;

import org.springframework.core.io.Resource;
import org.springframework.util.StringUtils;

import com.udapsoft.modular.core.context.ApplicationContextAwareImpl;

import freemarker.cache.ClassTemplateLoader;
import freemarker.cache.FileTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;

public class TemplateUtils {
	private static final String DEFAULT_ENCODING = "UTF-8";

	public static void generate(String templatePath, Class<?> loaderClass,
			Map model, OutputStream out) {
		try {
			generate(templatePath, loaderClass, model, new OutputStreamWriter(
					out));
		} catch (Exception e) {
			throw new TemplateGenerateException(e);
		}
	}

	public static void generate(String templatePath, Class loaderClass,
			Map model, Writer out) {
		if (!StringUtils.hasText(templatePath)) {
			throw new IllegalArgumentException("템플릿의 클래스 경로가 필요합니다. - "
					+ templatePath);
		}
		if (model == null) {
			throw new IllegalArgumentException("템플릿을 생성하기 위해서는 모델이 필요합니다.");
		}
		if (out == null) {
			throw new IllegalArgumentException("템플릿을 생성할 스트림이 필요합니다.");
		}
		String PATH = "/";
		try {
			Configuration cfg = new Configuration();
			cfg.setDefaultEncoding("UTF-8");

			cfg.setNumberFormat("0.######");

			int idx = templatePath.lastIndexOf("/");
			String prefix = templatePath.substring(0, idx);
			String templateFile = templatePath.substring(idx + 1);

			Template template = null;
			if ((templatePath.startsWith("file:"))
					|| (templatePath.startsWith("url:"))
					|| (templatePath.startsWith("classpath:"))) {
				Resource resource = ApplicationContextAwareImpl.getApplicationContext().getResource(prefix);
				FileTemplateLoader ftl = new FileTemplateLoader(
						resource.getFile());
				cfg.setTemplateLoader(ftl);
				template = cfg.getTemplate(templateFile);
			} else {
				Class<?> lc = null;
				if (templatePath.startsWith("/")) {
					lc = loaderClass == null ? TemplateUtils.class
							: loaderClass;
				} else {
					if (loaderClass == null) {
						throw new IllegalArgumentException(
								"템플릿의 클래스 경로가 상대경로일 경우에는 loaderClass가 필요합니다.");
					}
					lc = loaderClass;
				}
				ClassTemplateLoader ctl = new ClassTemplateLoader(lc, prefix);
				cfg.setTemplateLoader(ctl);

				template = cfg.getTemplate(templateFile);
			}
			template.process(model, out);
		} catch (Exception e) {
			throw new TemplateGenerateException(e);
		}
	}
}
