package net.sourceforge.rtf.template.freemarker;

import net.sourceforge.rtf.template.AbstractRTFDocumentTransformer;
import net.sourceforge.rtf.util.StringUtils;

public class RTFFreemarkerTransformerImpl extends AbstractRTFDocumentTransformer  {

    protected String getMacroEndForEach() {
        return "</#list>";
    }

    protected String getForeach(String fieldName, String fieldNameWithListInfo) {
        // Remove $ character
        if (fieldName.startsWith("$"))
            fieldName = fieldName.substring(1);
        String objectName = getObjectValueListInsideForEach(fieldName, fieldNameWithListInfo, false);
        String objectNameList = getItemListName(fieldName, fieldNameWithListInfo);
        StringBuffer foreachFreemarker = new StringBuffer("");
        foreachFreemarker.append("<#list ");
        foreachFreemarker.append(objectNameList );        
        foreachFreemarker.append(" as ");
        foreachFreemarker.append(objectName);
        foreachFreemarker.append("> ");
        return foreachFreemarker.toString(); 
    }
    
    protected String getObjectValueList(String fieldName, boolean withGetter)
    {
        return getObjectValueList(fieldName, withGetter, true);
    }
    
    protected String getObjectValueList(String fieldName, boolean withGetter, boolean escape) {
        String objectName = "";
        String getterName = "";
        if (fieldName.startsWith("$"))
            fieldName = fieldName.substring(1);
        objectName = fieldName;
        // get the 2 string betwew the last .
        // ex : $project.Name => objectName=project and getterName=Name
        // ex : $developer.Roles.Name => objectName=Roles and getterName=Name
        int dotLastIndex = fieldName.lastIndexOf(".");
        if (dotLastIndex != -1) {
            objectName = fieldName.substring(0, dotLastIndex);
            objectName = objectName.replace('.','_');
            getterName = fieldName.substring(dotLastIndex+ 1, fieldName.length());
        }
        if (withGetter && getterName.length() > 0)
            objectName = "item_" + objectName + "." + formatSubFieldName(getterName);
        else
            return "item_" + objectName;
        
        if (escape)
            return "${" + objectName + "}";
        return objectName;
    }

    protected String getObjectValueList(String fieldName, String fieldNameWithListInfo, boolean withGetter) {
       return "${"  + getObjectValueListInsideForEach(fieldName, fieldNameWithListInfo, withGetter) + "}";
    }
    
    protected String getObjectValueListInsideForEach(String fieldName, String fieldNameWithListInfo, boolean withGetter) {
        String objectName = "";
        if (fieldNameWithListInfo != null && fieldNameWithListInfo.length() > 0) {
            // eg : $workspace.[Developers].manager.Name must be transformed
            // into $item_workspace_Developers.manager.Name
            int indexLastEndedArray = fieldNameWithListInfo.lastIndexOf("]");
            if (indexLastEndedArray > 0) {
                // Test if there is several object after list (eg:manager.Name)
                if (fieldNameWithListInfo.indexOf(".", indexLastEndedArray + 2) > 0) {
                    String s = fieldNameWithListInfo.substring(0, indexLastEndedArray);
                    s = s.replaceAll("\\[", "");
                    objectName = getObjectValueList(s, true, false);
                    objectName = objectName.replace('.', '_');
                    if (!withGetter)
                        return objectName;
                    else {
                        return objectName + formatFieldName(fieldNameWithListInfo.substring(indexLastEndedArray + 1, fieldNameWithListInfo.length()));
                    }
                }
            }
        }
            
        // HERE : After list there is one getter
        
        // OLD transformation : 
        return getObjectValueList(fieldName, withGetter, false);
    }
    
    /**
     * For context=a.MyGetter Freemarker wait 
     * a.myGetter (lower case for the first letter)
     *  
     * @param fieldName
     * @return
     */
    protected String formatSubFieldName(String fieldName) {
        if (fieldName.length() > 0) {
            // the first character must be lower
            String characterFirst = fieldName.substring(0, 1);
            characterFirst = characterFirst.toLowerCase();
            fieldName = characterFirst + fieldName.substring(1, fieldName.length());
        }
        return fieldName;
    }  
    
    public String getTransformedFieldName(boolean fieldIsList, String fieldName) {
        if(fieldIsList)
            return fieldName;        
        String newFieldName = formatFieldName(fieldName);    
        return "${" + newFieldName + "}";
    }    
    
    private String formatFieldName(String fieldName) {
        StringBuffer newFieldName = new StringBuffer();
        String[] splitFieldName = StringUtils.split(fieldName, ".");
        for (int i = 0; i < splitFieldName.length; i++) {
            String subFieldName = splitFieldName[i];
            if (i > 0) {
                subFieldName = formatSubFieldName(subFieldName);
                newFieldName.append(".");
            }
            if (subFieldName.startsWith("$")) {
                subFieldName = subFieldName.substring(1, subFieldName.length());
            }
            newFieldName.append(subFieldName);
        }    
        if (fieldName.startsWith("."))            
            return "." + newFieldName.toString();
        return newFieldName.toString();
    }
    
	protected String getMacroPageBreak(String listName, String rtfPageBreakContent) {
		String itemNameList = getObjectValueList(listName, false, false);	
		return "<#if " + itemNameList + "_index lt $" + 
				listName +"?size) " + 
				rtfPageBreakContent + "</#if>";
	}
	
	protected String getMacroPageBreak(String listName, String rtfPageBreakContent, int groupByPerPageBreak) {
		String itemNameList = getObjectValueList(listName, false, false);		
		return " <#if " + itemNameList + "_index lt " + 
			   listName +"?size && " + itemNameList + "_index%" +  
			   String.valueOf(groupByPerPageBreak + 1) + "==" + 
			   String.valueOf(groupByPerPageBreak-1) + 
			   " > " + 
			   rtfPageBreakContent + "</#if> ";
	}    
    
    protected String getMacroIf(String condition) {
        return "<#if " + condition + " >";
    }
    protected String getMacroEndIf() {
        return "</#if>";
    }    
    
    protected String getMacroElse() {
        return "<#else>";
    }

}
