/* WikiTemplate - set of functions related to wiki {{templates|..}}.
 *
 * Copyright (c) 2012 Andrew Krizhanovsky <andrew.krizhanovsky at gmail.com>
 * Distributed under EPL/LGPL/GPL/AL/BSD multi-license.
 */
package wikokit.base.wikipedia.util.template;


/** Set of functions related to wiki {{templates|..}}.
 */
public class TemplateParser {
    
    //   Replace all substrings "target" by "replacement" in the part of "source_text" 
    //   which contains template titled "template_name".
    //public static String replaceInTemplate(String source_text, String template_name, 
    //                                       String target, String replacement) {
        
      
    /** Expands template parameters, 
     * replaces all substrings "target" by "replacement" in the part of "source_text" 
     * which contains template titled "template_name"; removes template name and brackets,
     * e.g. "abc{{template|start..target..end}}xyz" -> "abcstart..replacement..endxyz"
     *
     * @param text      source text with quotation template
     * @return text with replaced text
     */
    public static String expandTemplateParams(String source_text, String template_name, 
                                           String target, String replacement) {
        // 1. find position of "{{$template_name|" = pos_template_start
        // 2. find position of "}}" = pos_template_end
        // 3. result text = concat( source_text[0, pos_template_start],
        //                          replace([pos_template_start, pos_template_end], target, replacement),
        //                          source_text[pos_template_end, length])
        
        if(null == template_name || template_name.length() < 1)
            return source_text;
        
        int p = source_text.toLowerCase().indexOf("{{" + template_name.toLowerCase() + "|");
        if(-1 == p)
            return source_text; // this template is absent in source text
        int pos_template_start = p;
        
        p = source_text.indexOf("}}", pos_template_start + template_name.length());
        if(-1 == p)
            return source_text; // end of template is absent
        int pos_template_end = p;
                                                                                                // 3= 1 + 2 = len("{{") + len("|") in "{{template|"
        String template_body = source_text.substring(pos_template_start + template_name.length() + 3, pos_template_end);
        template_body = template_body.replace(target, replacement);
        
        StringBuilder result = new StringBuilder();
        result.append( source_text.substring(0, pos_template_start) );
        result.append( template_body );
        result.append( source_text.substring( pos_template_end+2 ) );
        
        return result.toString();
    }
    
    /** Expands template parameter, 
     * e.g. "abc {{template|some text}} xyz" -> "abc some text xyz"
     * e.g. "abc {{template|some {{subtemplate|}} text}} xyz" -> "abc some {{subtemplate|}} text xyz"
     *
     * @param text      source text with template
     * @return expanded text
     */
    public static String expandTemplateWithOneParameter(String source_text, String template_name) {
        
        // 1. find position of "{{$template_name|" = pos_template_start
        // 2. find position of "}}" = pos_template_end
        // 3. result text = concat( source_text[0, pos_template_start],
        //                          source_text[pos_template_start + template length, pos_template_end],
        //                          source_text[pos_template_end, length])
        
        if(null == template_name || template_name.length() < 1)
            return source_text;
        
        int p = source_text.toLowerCase().indexOf("{{" + template_name.toLowerCase() + "|");
        if(-1 == p)
            return source_text; // this template is absent in source text
        int pos_template_start = p;
        
        // p = source_text.indexOf("}}", pos_template_start + template_name.length());
// todo find
        p = indexOfClosingBracketsSameLevel(source_text, pos_template_start + template_name.length(), "{{", "}}");
        if(-1 == p)
            return source_text; // end of template is absent
        int pos_template_end = p;
        
                                                                                                // 3= 1 + 2 = len("{{") + len("|") in "{{template|"
        String template_body = source_text.substring(pos_template_start + template_name.length() + 3, pos_template_end);
        
        StringBuilder result = new StringBuilder();
        result.append( source_text.substring(0, pos_template_start) );
        result.append( template_body );
        result.append( source_text.substring( pos_template_end+2 ) );
        
        return result.toString();
    }
    
    
    // p = source_text.indexOfSameLevelClosingBrackets(source_text, "}}", pos_template_start + template_name.length());
        //if(-1 == p)
    /** Finds index of the closing template bracket at same level, 
     * e.g. "0        10            23      30                  abc {{template|some text}} xyz" -> "abc some text xyz"
     * e.g. "some text {{subtemplate|}} text}} xyz" -> 30 is the position of the closing brackets of the same level
     *
     * @param text      source text with template
     * @return index of closing bracket, -1 if there is some error or there is no any closing brackets
     */
    public static int indexOfClosingBracketsSameLevel(String text, int start_pos, String open_brackets, String closing_brackets) {
        
        int pos_opening_bracket = text.indexOf(open_brackets, start_pos);
        int pos_closing_bracket = text.indexOf(closing_brackets, start_pos);
        if(-1 == pos_closing_bracket)
            return -1;
        
        if(-1 == pos_opening_bracket || pos_closing_bracket < pos_opening_bracket)
            return pos_closing_bracket; // "}}" or "}} ... {{"
        
        // ok, now: {{ ... }}, let's go further
        while(-1 != pos_closing_bracket) {
            
            start_pos = pos_closing_bracket + closing_brackets.length();
                    
            pos_opening_bracket = text.indexOf(open_brackets, start_pos);
            pos_closing_bracket = text.indexOf(closing_brackets, start_pos);
            
            if(-1 == pos_closing_bracket)
                return -1;
        
            if(-1 == pos_opening_bracket || pos_closing_bracket < pos_opening_bracket)
                return pos_closing_bracket; // "}}" or "}} ... {{"
        }
        
        return -1;
    }
}
