/*
* Copyright 2014 - LAit SpA
*				 Realizzato da Icona Management srl su commessa LAit SpA
* Copyright 2015- LAit SpA
*                                                  Aggiornato da LAit SpA
*
* Concesso in licenza a norma dell'EUPL, versione 1.1 o
* successive dell'EUPL (la "Licenza")– non appena saranno
* approvate dalla Commissione europea;
* Non è possibile utilizzare l'opera salvo nel rispetto della Licenza.
* È possibile ottenere una copia della Licenza al seguente indirizzo:
*
* http://ec.europa.eu/idabc/eupl
*
* Salvo diversamente indicato dalla legge applicabile o
* concordato per iscritto, il software distribuito secondo
* i termini della Licenza è distribuito "TAL QUALE",
* SENZA GARANZIE O CONDIZIONI DI ALCUN TIPO,
* esplicite o implicite.
* Si veda la Licenza per la lingua specifica che disciplina
* le autorizzazioni e le limitazioni secondo i termini della
* Licenza.
*/
package it.laitspa.cpf.faces.utils.component;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.faces.component.UIComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.component.UIInput;
import javax.faces.component.UIOutput;
import javax.faces.component.html.HtmlOutputLabel;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;

import org.richfaces.component.html.HtmlCalendar;

public class CpfPanelLayout
  extends UIComponentBase
{
  /**
   * 
   */
  public static final String COMPONENT_TYPE = "panelGrid";
  private boolean            rendered       = true;
  private Integer            columns;
  private String             width;

  public CpfPanelLayout()
  {
    setRendered(rendered);
    setRendererType(null);
  }

  public String getWidth()
  {
    return width;
  }

  public void setWidth(String width)
  {
    this.width = width;
  }

  public Integer getColumns()
  {
    return columns;
  }

  public void setColumns(Integer columns)
  {
    this.columns = columns;
  }

  @Override
  public boolean getRendersChildren()
  {
    return true;
  }

  @Override
  public void encodeBegin(FacesContext context)
    throws IOException
  {
    ResponseWriter writer = context.getResponseWriter();

    String tableW = getWidth();
    if(tableW == null)
      tableW = "auto";

    // Encode tr:panelFormLayout
    //
    writer.startElement("div", this);
    writer.writeAttribute("class", "af_panelFormLayout", "class");
    writer.startElement("table", this);
    writer.writeAttribute("style", "width: " + tableW + "; ", "style");
    writer.startElement("tbody", this);
  }

  @Override
  public void encodeChildren(FacesContext context)
    throws IOException
  {
    ResponseWriter writer = context.getResponseWriter();
    List<UIComponent> childs = getChildren();

    if(this.columns == null || this.columns.equals(new Integer(0)))
      this.columns = 2;

    if(childs == null || childs.size() == 0)
      return;

    int groupcount = 0;

    for(UIComponent c : childs)
    {

      if(!c.isRendered())
        continue;

      if(groupcount == 0)
      {
        writeRow(writer);
      }

      Map<String, Object> childAttributes = c.getAttributes();
      String styleClass = (String)childAttributes.get("styleClass");
      if(styleClass != null && styleClass.endsWith("textline"))
      {
        // Encode child in single row
        //
        writer.startElement("td", this);
        writer.writeAttribute("colspan", this.columns - groupcount, "colSpan");
        writer.writeAttribute("align", "left", "align");
        writer.writeAttribute("class", "af_panelFormLayout_column", "class");
        writeComponent(context, c);
        groupcount = this.columns;
        writer.endElement("td");
      }
      else
      {
        // Encode child
        //
        writer.startElement("td", this);
        writer.writeAttribute("colspan", "1", "colspan");
        writer.writeAttribute("class", "af_panelFormLayout_column", "class");
        writeComponent(context, c);
        groupcount++;
        writer.endElement("td");
      }

      if(groupcount == this.columns)
      {
        // Reset count
        //
        groupcount = 0;

        // Close panelFormLayout
        //
        writer.endElement("tr");
      }
    }

    // Check if child is pending
    //
    if(groupcount != 0)
    {
      // Close panelFormLayout
      //
      closeWithColumn(writer, groupcount);
    }
  }

  private void writeComponent(FacesContext context, UIComponent c)
    throws IOException
  {

    if (!(c instanceof UIInput)
        || !(c instanceof UIOutput))
    {
      c.encodeBegin(context);
      
      // Recursive encoding.
      //
      List<UIComponent> childs = c.getChildren();
      for (UIComponent cl : childs)
        writeComponent(context, cl);
      
      c.encodeEnd(context);
      
      return;
    }
    
    
    ResponseWriter writer = context.getResponseWriter();
    

    // Start new table for component child.
    //
    writer.startElement("div", c);
    writer.writeAttribute("class", "af_panelFormLayout_content", "class");
    writer.startElement("table", c);
    writer.writeAttribute("style", "width: 100%; ", "style");
    writer.startElement("tbody", c);

    writer.startElement("tr", c);

    if(c instanceof UIInput)
    {

      // Check for styleClass
      //
      String styleClass = null;
      String styleKey = "styleClass";
      if(c instanceof HtmlCalendar)
        styleKey = "inputClass";

      if(c.getAttributes().get(styleKey) == null)
      {
        styleClass = "celltext";
        if(((UIInput)c).isRequired())
          styleClass = "mandatory".concat(styleClass);

        if(c instanceof HtmlCalendar)
        {
          HtmlCalendar cal = (HtmlCalendar)c;
          cal.setInputClass(styleClass);
        }
        else
          c.getAttributes().put("styleClass", styleClass);

      }
      else if(c.getAttributes().get(styleKey) != null)
      {
        styleClass = (String)c.getAttributes().get(styleKey);
        if(styleClass.equals("celltextline") && ((UIInput)c).isRequired())
        {
          styleClass = "mandatory".concat(styleClass);
          c.getAttributes().put(styleKey, styleClass);
        }
      }

      // Adding OutputLabel
      //
      HtmlOutputLabel label =
          (HtmlOutputLabel)context.getApplication().createComponent(HtmlOutputLabel.COMPONENT_TYPE);
      label.setId(buildIdForComponent());

      if(c.getId() == null)
        c.setId(buildIdForComponent());

      label.setFor(c.getId());

      String labelValue = (String)c.getAttributes().get("label");
      
      // Put custom label for validation. 
      //
      c.getAttributes().put("label_custom", labelValue);
      
      // Add some message to show when label is null!
      //
      if(labelValue == null)
        labelValue = "Undefined label attribute for component.";

      label.setValue(labelValue);

      writer.startElement("td", label);
      writer.writeAttribute("colspan", "1", "colspan");
      writer.writeAttribute("class", "af_panelFormLayout_label", "class");
      label.encodeAll(context);
      writer.endElement("td");

      // Adding required icon.
      //
      writer.startElement("td", label);
      writer.writeAttribute("colspan", "1", "colspan");
      writer.writeAttribute("width", "7px", "width");
      if(((UIInput)c).isRequired() || (styleClass != null && styleClass.startsWith("mandatory")))
        writer.writeAttribute("class", "af_panelFormLayout_required_content", "class");
      writer.endElement("td");
    }

    // Adding one column for component inside row.
    //
    writer.startElement("td", c);
    writer.writeAttribute("colspan", "1", "colspan");
    writer.writeAttribute("class", "af_panelFormLayout_column", "class");
    c.encodeAll(context);
    writer.endElement("td");

    // Closing row.
    //
    writer.endElement("tr");

    // Adding message for component.
    //
    /*
     * if(c instanceof UIInput) { writer.startElement("tr", c);
     * 
     * // Adding one column for component inside row with colspan 2. //
     * writer.startElement("td", c); writer.writeAttribute("colspan", "2",
     * "colspan"); writer.writeAttribute("class", "af_panelFormLayout_column",
     * "class");
     * 
     * UIMessage message =
     * (UIMessage)context.getApplication().createComponent(UIMessage
     * .COMPONENT_TYPE); message.setId(buildIdForComponent());
     * message.setFor(c.getId()); message.setParent(c);
     * 
     * message.encodeAll(context);
     * 
     * writer.endElement("td"); writer.endElement("tr"); }
     */

    // Close component table
    //
    writer.endElement("tbody");
    writer.endElement("table");
    writer.endElement("div");
  }

  private void writeRow(ResponseWriter writer)
    throws IOException
  {
    writer.startElement("tr", this);
  }

  private void closeWithColumn(ResponseWriter writer, int col)
    throws IOException
  {
    for(int i = 0; i < this.columns - col; i++)
    {
      writer.startElement("td", this);
      writer.writeAttribute("colspan", "1", "colspan");
      writer.writeAttribute("class", "af_panelFormLayout_column", "class");
      writer.endElement("td");
    }
    writer.endElement("tr");
  }

  @Override
  public void encodeEnd(FacesContext context)
    throws IOException
  {
    ResponseWriter writer = context.getResponseWriter();
    writer.endElement("tbody");
    writer.endElement("table");
    writer.endElement("div");
  }

  @Override
  public String getFamily()
  {
    return COMPONENT_TYPE;
  }

  public static String getComponentType()
  {
    return COMPONENT_TYPE;
  }

  private String buildIdForComponent()
  {
    return "L" + UUID.randomUUID().toString().replace("-", "");
  }

  @Override
  public Object saveState(FacesContext facesContext)
  {


    Object values[] = new Object[3];
    values[0] = super.saveState(facesContext);
    values[1] = this.columns;
    values[2] = this.width;
    return values;

  }

  @Override
  public void restoreState(FacesContext facesContext, Object state)
  {
    Object values[] = (Object[])state;
    super.restoreState(facesContext, values[0]);
    this.columns = (Integer)values[1];
    this.width = (String)values[2];
    
  
  }
}
