/*
 * 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.freemarker;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletContext;

import nuts.core.lang.ClassUtils;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import freemarker.cache.ClassTemplateLoader;
import freemarker.cache.FileTemplateLoader;
import freemarker.cache.MultiTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.cache.WebappTemplateLoader;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;

/**
 * FreemarkerManager
 * 
 * @see org.apache.struts2.views.freemarker.FreemarkerManager
 */
public class FreemarkerManager extends org.apache.struts2.views.freemarker.FreemarkerManager {

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

    /**
     * Create the template loader. The default implementation will create a
     * {@link ClassTemplateLoader} if the template path starts with "class://",
     * a {@link FileTemplateLoader} if the template path starts with "file://",
     * and a {@link WebappTemplateLoader} otherwise.
     * @param templatePath the template path to create a loader for
     * @return a newly created template loader
     * @throws IOException
     */
	@Override
	protected TemplateLoader createTemplateLoader(ServletContext servletContext, String templatePath) {
		List<TemplateLoader> tls = new ArrayList<TemplateLoader>();

		if (templatePath != null) {
			String[] ts = StringUtils.split(templatePath);
			for (String t : ts) {
				try {
					if (t.startsWith("file://")) {
						tls.add(new FileTemplateLoader(new File(t.substring(7))));
					}
					else if (t.startsWith("web://")) {
						tls.add(new WebappTemplateLoader(servletContext, t.substring(6)));
					}
					else if (t.startsWith("class://")) {
						String path = t.substring(8);
				        if(!path.endsWith("/")) {
				            path += "/";
				        }
				        if (!path.startsWith("/")) {
				            path = "/" + path;
				        }
						tls.add(new ClassTemplateLoader(getClass(), path));
					}
					else if (t.startsWith("bean://")) {
						tls.add((TemplateLoader)ClassUtils.newInstance(t.substring(7)));
					}
					else {
						log.warn("Invalid template path - " + t);
					}
				}
				catch (Exception e) {
					log.warn("Invalid template path - " + t, e);
				}
			}
		}
		else {
			// presume that most apps will require the class and webapp template loader
			// if people wish to
			tls.add(new WebappTemplateLoader(servletContext));
			tls.add(new ClassTemplateLoader(getClass(), "/"));
		}

		return new MultiTemplateLoader(tls.toArray(new TemplateLoader[tls.size()]));
	}

    /**
     * Create the instance of the freemarker Configuration object.
     * <p/>
     * this implementation
     * <ul>
     * <li>obtains the default configuration from Configuration.getDefaultConfiguration()
     * <li>sets up template loading from a ClassTemplateLoader and a WebappTemplateLoader
     * <li>sets up the object wrapper to be the BeansWrapper
     * <li>loads settings from the classpath file /freemarker.properties
     * </ul>
     *
     * @param servletContext
     */
	@Override
    protected freemarker.template.Configuration createConfiguration(ServletContext servletContext) throws TemplateException {
    	freemarker.template.Configuration configuration = super.createConfiguration(servletContext);
    	
        configuration.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);

        return configuration;
    }

}
