package net.sf.jasperreports.engine.fill;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import net.sf.jasperreports.engine.JRChild;
import net.sf.jasperreports.engine.JRElement;
import net.sf.jasperreports.engine.JRElementGroup;
import net.sf.jasperreports.engine.JRVisitable;
import net.sf.jasperreports.engine.JRVisitor;

public class JRFillElementGroup implements JRElementGroup, JRFillCloneable {
  protected List children = new ArrayList();
  
  protected JRElementGroup elementGroup = null;
  
  protected JRFillElement[] elements = null;
  
  private JRElement topElementInGroup = null;
  
  private JRElement bottomElementInGroup = null;
  
  private int stretchHeightDiff = 0;
  
  protected JRFillElementGroup(JRElementGroup elementGrp, JRFillObjectFactory factory) {
    factory.put(elementGrp, this);
    if (elementGrp != null) {
      List list = elementGrp.getChildren();
      if (list != null && list.size() > 0)
        for (int i = 0; i < list.size(); i++) {
          JRChild child = list.get(i);
          child = (JRChild)factory.getVisitResult((JRVisitable)child);
          this.children.add(child);
        }  
      getElements();
      this.elementGroup = (JRElementGroup)factory.getVisitResult((JRVisitable)elementGrp.getElementGroup());
    } 
  }
  
  protected JRFillElementGroup(JRFillElementGroup elementGrp, JRFillCloneFactory factory) {
    factory.put(elementGrp, this);
    List list = elementGrp.getChildren();
    if (list != null)
      for (int i = 0; i < list.size(); i++) {
        JRFillCloneable child = list.get(i);
        JRFillCloneable clone = child.createClone(factory);
        this.children.add(clone);
      }  
    getElements();
    this.elementGroup = (JRFillElementGroup)factory.getClone((JRFillElementGroup)elementGrp.getElementGroup());
  }
  
  public List getChildren() {
    return this.children;
  }
  
  public JRElementGroup getElementGroup() {
    return this.elementGroup;
  }
  
  public JRElement[] getElements() {
    if (this.elements == null)
      if (this.children != null) {
        List allElements = new ArrayList();
        Object child = null;
        JRElement[] childElementArray = null;
        for (int i = 0; i < this.children.size(); i++) {
          child = this.children.get(i);
          if (child instanceof JRFillElement) {
            allElements.add(child);
          } else if (child instanceof JRFillElementGroup) {
            childElementArray = ((JRFillElementGroup)child).getElements();
            if (childElementArray != null)
              allElements.addAll(Arrays.asList((Object[])childElementArray)); 
          } 
        } 
        this.elements = new JRFillElement[allElements.size()];
        allElements.toArray(this.elements);
      }  
    return (JRElement[])this.elements;
  }
  
  public JRElement getElementByKey(String key) {
    return null;
  }
  
  protected void reset() {
    this.topElementInGroup = null;
  }
  
  protected int getStretchHeightDiff() {
    if (this.topElementInGroup == null) {
      this.stretchHeightDiff = 0;
      setTopBottomElements();
      JRElement[] allElements = getElements();
      if (allElements != null && allElements.length > 0) {
        JRFillElement topElem = null;
        JRFillElement bottomElem = null;
        for (int i = 0; i < allElements.length; i++) {
          JRFillElement element = (JRFillElement)allElements[i];
          if (element.isToPrint()) {
            if (topElem == null || (topElem != null && element.getRelativeY() + element.getStretchHeight() < topElem.getRelativeY() + topElem.getStretchHeight()))
              topElem = element; 
            if (bottomElem == null || (bottomElem != null && element.getRelativeY() + element.getStretchHeight() > bottomElem.getRelativeY() + bottomElem.getStretchHeight()))
              bottomElem = element; 
          } 
        } 
        if (topElem != null)
          this.stretchHeightDiff = bottomElem.getRelativeY() + bottomElem.getStretchHeight() - topElem.getRelativeY() - this.bottomElementInGroup.getY() + this.bottomElementInGroup.getHeight() - this.topElementInGroup.getY(); 
        if (this.stretchHeightDiff < 0)
          this.stretchHeightDiff = 0; 
      } 
    } 
    return this.stretchHeightDiff;
  }
  
  private void setTopBottomElements() {
    JRElement[] allElements = getElements();
    if (allElements != null && allElements.length > 0)
      for (int i = 0; i < allElements.length; i++) {
        if (this.topElementInGroup == null || (this.topElementInGroup != null && allElements[i].getY() + allElements[i].getHeight() < this.topElementInGroup.getY() + this.topElementInGroup.getHeight()))
          this.topElementInGroup = allElements[i]; 
        if (this.bottomElementInGroup == null || (this.bottomElementInGroup != null && allElements[i].getY() + allElements[i].getHeight() > this.bottomElementInGroup.getY() + this.bottomElementInGroup.getHeight()))
          this.bottomElementInGroup = allElements[i]; 
      }  
  }
  
  public void visit(JRVisitor visitor) {
    visitor.visitElementGroup(this);
  }
  
  public JRFillCloneable createClone(JRFillCloneFactory factory) {
    return new JRFillElementGroup(this, factory);
  }
  
  public Object clone() {
    return null;
  }
  
  public Object clone(JRElementGroup parentGroup) {
    return null;
  }
}
