/*
 * This file is part of Nuts Framework.
 * Copyright (C) 2009 Nuts Develop Team.
 *
 * Nuts Framework is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License any later version.
 *
 * Nuts Framework is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Nuts Framework. If not, see <http://www.gnu.org/licenses/>.
 */
package nuts.exts.struts2.views.java;

import java.util.HashMap;
import java.util.StringTokenizer;

import nuts.exts.struts2.views.java.nthtml.NthtmlTheme;
import nuts.exts.struts2.views.java.nxhtml.NxhtmlTheme;
import nuts.exts.struts2.views.java.simple.SimpleTheme;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.StrutsException;
import org.apache.struts2.components.template.BaseTemplateEngine;
import org.apache.struts2.components.template.Template;
import org.apache.struts2.components.template.TemplateRenderingContext;

import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.ClassLoaderUtil;

/**
 * Template engine that renders tags using java implementations
 */
public class JavaTemplateEngine extends BaseTemplateEngine {

	private static final Log log = LogFactory.getLog(JavaTemplateEngine.class);

	private Themes themes = new Themes();
	
	public JavaTemplateEngine() {
		themes.add(new SimpleTheme());
		themes.add(new NthtmlTheme());
		themes.add(new NxhtmlTheme());
	}

	@Override
	protected String getSuffix() {
		return "java";
	}

	public void renderTemplate(TemplateRenderingContext templateContext)
			throws Exception {
		Template t = templateContext.getTemplate();
		Theme theme = themes.get(t.getTheme());
		if (theme == null) {
			throw new StrutsException("Cannot render tag [" + t.getName()
					+ "] because theme [" + t.getTheme() + "] was not found.");
		}
		theme.renderTemplate(templateContext);
	}

	private class Themes {
		private HashMap<String, Theme> themes = new HashMap<String, Theme>();

		public void add(Theme theme) {
			themes.put(theme.getName(), theme);
		}

		public Theme get(String name) {
			return themes.get(name);
		}
	}

	/**
	 * Allows for providing custom theme classes (implementations of the
	 * org.apache.struts2.views.java.Theme) interface for custom rendering of
	 * tags using the javatemplates engine
	 * 
	 * @param themeClasses a comma delimited list of custom theme class names
	 */
	@Inject(value = "struts.javatemplates.customThemes", required = false)
	public void setThemeClasses(String themeClasses) throws Exception {
		StringTokenizer customThemes = new StringTokenizer(themeClasses, ",");

		while (customThemes.hasMoreTokens()) {
			String themeClass = customThemes.nextToken().trim();
			try {
				log.info("Registering custom theme '" + themeClass
						+ "' to javatemplates engine");

				// ObjectFactory.getObjectFactory().buildBean(ClassLoaderUtil.loadClass(themeClass,
				// getClass()), null);
				themes.add((Theme)ClassLoaderUtil.loadClass(themeClass,
						getClass()).newInstance());
			}
			catch (ClassCastException cce) {
				log.error("Invalid java them class '"
						+ themeClass
						+ "'. Class does not implement 'org.apache.struts2.views.java.Theme' interface");
				throw cce;
			}
			catch (ClassNotFoundException cnf) {
				log.error("Invalid java theme class '" + themeClass
						+ "'. Class not found");
				throw cnf;
			}
			catch (Exception e) {
				log.error("Could not find messages file " + themeClass
						+ ".properties. Skipping");
				throw e;
			}
		}
	}
}
