package hirondelle.web4j.ui.tag;

import java.io.IOException;
import javax.servlet.jsp.JspException;
import java.util.regex.*;
import hirondelle.web4j.ui.tag.TagHelper;
import hirondelle.web4j.util.Regex;
import hirondelle.web4j.util.Util;

/**
 Generate table rows which alternate in appearance, to increase legibility.

 <P>The body of this tag contains one or more <tt>TR</tt> tags. Each <tt>TR</tt> tag contains a 
 <tt>class</tt> attribute, specifying a Cascading Style Sheet class. This tag 
 will simply remove or update the <tt>class</tt> attribute for alternate occurrences of 
 each <tt>TR</tt> tag found in its body.
 
 <P>If the optional <tt>altClass</tt> attribute is specified, then the <tt>class</tt> 
 attribute of each <tt>TR</tt> is updated to an alternate value, instead of being removed. 
*/
public final class AlternatingRow extends TagHelper {
 
  /**
   Optional name of a CSS class. 
   
   <P>The CSS class for each <tt>TR</tt> tag found in the body of this tag will be 
   updated to this value, for alternating rows. If this item is not specified, then the <tt>TR</tt>'s 
   class attribute is simply removed instead of updated.
   
   @param aAltClass must have content.
  */
  public void setAltClass(String aAltClass){
    checkForContent("AltClass", aAltClass);
    fAltClass = aAltClass;
  }
  
  /**
   For each <tt>TR</tt> tag found in the body, remove or update the <tt>class</tt> attribute.
   
   <P>If no <tt>altClass</tt> is specified, then the <tt>class</tt> attribute is simply removed entirely. 
   Otherwise, it updated to the <tt>altClass</tt> value.
  */
  protected String getEmittedText(String aOriginalBody) throws JspException, IOException {
    StringBuffer result = new StringBuffer();
    Matcher matcher = TR_PATTERN.matcher(aOriginalBody);
    int matchIdx = 0;
    while (matcher.find()){
      ++ matchIdx;
      if( isEvenRow(matchIdx) ){
        matcher.appendReplacement(result, getReplacement(matcher));
      }
      else {
        String noChange = matcher.group(0);
        matcher.appendReplacement(result, noChange);
      }
    }
    matcher.appendTail(result);
    return result.toString();
  }
  
  // PRIVATE //
  private String fAltClass;
  private static final Pattern TR_PATTERN = Pattern.compile("<tr" + "("+ Regex.ALL_BUT_END_OF_TAG + ")" + "class=" + Regex.QUOTED_ATTR + "("+ Regex.ALL_BUT_END_OF_TAG + ")"+ ">", Pattern.CASE_INSENSITIVE);
  
  private String getReplacement(Matcher aMatcher){
    //construct replacement: <TR + G1 + class='G2' + G3 + >
    StringBuilder result = new StringBuilder("<TR" + aMatcher.group(1)); 
    if( Util.textHasContent(fAltClass) ){
      result.append("class='" + fAltClass + "'"); 
    }
    result.append(aMatcher.group(3) + ">");
    return result.toString();
  }
  
  private boolean isEvenRow(int aMatchIdx){
    return aMatchIdx % 2 == 0;
  }
}
