package net.sourceforge.rtf.helper;

import java.util.HashMap;
import java.util.Map;

import net.sourceforge.rtf.IRTFDocumentParser;
import net.sourceforge.rtf.IRTFDocumentTransformer;
import net.sourceforge.rtf.ITemplateEngine;
import net.sourceforge.rtf.RTFTemplate;
import net.sourceforge.rtf.UnsupportedRTFDocumentParser;
import net.sourceforge.rtf.UnsupportedRTFDocumentTransformer;
import net.sourceforge.rtf.UnsupportedRTFTemplate;
import net.sourceforge.rtf.UnsupportedTemplateEngine;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class RTFTemplateBuilder {
    
    public static final String DEFAULT_FREEMARKER_RTFTEMPLATE = "ftlRTFTemplate";    
    public static final String DEFAULT_VELOCITY_RTFTEMPLATE = "vmRTFTemplate";
    
    public static final String DEFAULT_RTFDOCUMENTPARSER = "defaultRTFParser";
    
    public static final String VELOCITY_ENGINE = "vm";
    public static final String VELOCITY_TRANSFORMER = "vmTransformer";    
    public static final String FREEMARKER_ENGINE = "ftl";
    public static final String FREEMARKER_TRANSFORMER = "ftlTransformer";
    
    private static final String DEFAULT_CONFIG = 
        "net/sourceforge/rtf/rtftemplate-config.xml";
    
    private static Map rtfTemplateBuilderMap = new HashMap();; 
    
    private ApplicationContext applicationContext;
    
    private RTFTemplateBuilder() {
        
    }
            
    public static RTFTemplateBuilder newRTFTemplateBuilder() {
        RTFTemplateBuilder builder  = (RTFTemplateBuilder)rtfTemplateBuilderMap.get(DEFAULT_CONFIG);
        if(builder == null) {                   
            builder = newRTFTemplateBuilder(DEFAULT_CONFIG, new ClassPathXmlApplicationContext(DEFAULT_CONFIG));
        }
        return builder;
    }
    
    public static RTFTemplateBuilder newRTFTemplateBuilder(String configLocation) {
        RTFTemplateBuilder builder  = (RTFTemplateBuilder)rtfTemplateBuilderMap.get(configLocation);
        if(builder == null) {                   
            builder = newRTFTemplateBuilder(configLocation, new FileSystemXmlApplicationContext(configLocation));            
        }
        return builder;        
    }

    public static RTFTemplateBuilder newRTFTemplateBuilder(String key, ApplicationContext applicationContext) {
        RTFTemplateBuilder builder  = (RTFTemplateBuilder)rtfTemplateBuilderMap.get(key);
        if(builder == null) {   
            builder = newRTFTemplateBuilder(applicationContext);
            rtfTemplateBuilderMap.put(key, builder);
        }        
        return builder;
    }
    
    public static RTFTemplateBuilder newRTFTemplateBuilder(ApplicationContext applicationContext) {
        RTFTemplateBuilder builder = new RTFTemplateBuilder();
        builder.applicationContext = applicationContext;
        return builder;
    }    
    
    /**
     * Return RTFTemplate implementation of rtf template type
     * <code>rtfTemplateType</code>. Throw 
     * exception <code>UnsupportedRTFTemplate</code> if template
     * type is not supported.
     * 
     * @param rtfTemplateType the rtfTemplateType.
     * @return the result.
     * @throws UnsupportedRTFTemplate exception.
     */
    public RTFTemplate newRTFTemplate(String rtfTemplateType)
        throws UnsupportedRTFTemplate {
        RTFTemplate rtfTemplate = (RTFTemplate)
            applicationContext.getBean(rtfTemplateType);
        if (rtfTemplate == null) {
            throw new UnsupportedRTFTemplate(rtfTemplateType);
        }
        return rtfTemplate;
    }
    
    /**
     * Reurn RTFTemplate with Velocity Implementation.
     * @return the result.
     * @throws UnsupportedRTFTemplate the exception.
     */
    public RTFTemplate newRTFTemplate() throws UnsupportedRTFTemplate
    {
        return newRTFTemplate(DEFAULT_VELOCITY_RTFTEMPLATE);
    }
    
    /**
     * Return TemplateEngine implementation of template engine type
     * <code>templateEngineType</code>. Throw 
     * exception <code>UnsupportedTemplateEngine</code> if template
     * engine is not supported.
     * 
     * @param templateEngineType template engine type (fm, vm,...)
     * @return the result.
     * @throws UnsupportedTemplateEngine the exception.
     */
    public ITemplateEngine newTemplateEngine(String templateEngineType) 
        throws UnsupportedTemplateEngine {
        ITemplateEngine templateEngine = (ITemplateEngine) 
                applicationContext.getBean(templateEngineType);
        if (templateEngine == null)
            throw new UnsupportedTemplateEngine(templateEngineType);
        return templateEngine;
    }
    
    /**
     * Return RTFDocumentTransformer implementation of template engine type
     * <code>rtfDocumentTransformerType</code>. Throw 
     * exception <code>UnsupportedRTFDocumentTransformer</code> if template
     * engine is not supported.
     * 
     * @param rtfDocumentTransformerType the rtf Document Transformer Type.
     * @return the result.
     * @throws UnsupportedRTFDocumentTransformer the exception.
     */
    public IRTFDocumentTransformer newRTFDocumentTransformer(String rtfDocumentTransformerType)
        throws UnsupportedRTFDocumentTransformer {
        IRTFDocumentTransformer rtfDocumentTransformer = (IRTFDocumentTransformer) 
                applicationContext.getBean(rtfDocumentTransformerType);
        if (rtfDocumentTransformer == null)
            throw new UnsupportedRTFDocumentTransformer(rtfDocumentTransformerType);
        return rtfDocumentTransformer;
    }  
    
    /**
     * Return RTFDocumentParser implementation of template engine type
     * <code>rtfDocumentParserType</code>. Throw 
     * exception <code>UnsupportedRTFDocumentParser</code> if template
     * engine is not supported.
     * 
     * @param rtfDocumentParserType the rtf Document Parser Type.
     * @return the result.
     * @throws UnsupportedRTFDocumentParser the exception.
     */
    public IRTFDocumentParser newRTFDocumentParser(String rtfDocumentParserType)
        throws UnsupportedRTFDocumentParser {
        IRTFDocumentParser rtfDocumentParser = (IRTFDocumentParser) 
                applicationContext.getBean(rtfDocumentParserType);
        if (rtfDocumentParser == null)
            throw new UnsupportedRTFDocumentParser(rtfDocumentParserType);
        return rtfDocumentParser;
    }      
    
    public IRTFDocumentParser newRTFDocumentParser() 
        throws UnsupportedRTFDocumentParser {
        return newRTFDocumentParser(DEFAULT_RTFDOCUMENTPARSER);
    }
    
    
}
