package net.sf.jasperreports.engine.base;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import net.sf.jasperreports.crosstabs.JRCrosstab;
import net.sf.jasperreports.engine.JRChild;
import net.sf.jasperreports.engine.JRElement;
import net.sf.jasperreports.engine.JRElementGroup;
import net.sf.jasperreports.engine.JRFrame;
import net.sf.jasperreports.engine.JRRuntimeException;
import net.sf.jasperreports.engine.JRVisitable;
import net.sf.jasperreports.engine.JRVisitor;

public class JRBaseElementGroup implements JRElementGroup, Serializable {
  private static final long serialVersionUID = 10200L;
  
  protected List children = new ArrayList();
  
  protected JRElementGroup elementGroup = null;
  
  protected JRBaseElementGroup() {}
  
  protected JRBaseElementGroup(JRElementGroup elementGrp, JRBaseObjectFactory factory) {
    factory.put(elementGrp, this);
    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);
      }  
    this.elementGroup = (JRElementGroup)factory.getVisitResult((JRVisitable)elementGrp.getElementGroup());
  }
  
  public List getChildren() {
    return this.children;
  }
  
  public JRElementGroup getElementGroup() {
    return this.elementGroup;
  }
  
  public static JRElement[] getElements(List children) {
    JRElement[] elements = null;
    if (children != null) {
      List allElements = new ArrayList();
      Object child = null;
      JRElement[] childElementArray = null;
      for (int i = 0; i < children.size(); i++) {
        child = children.get(i);
        if (child instanceof JRElement) {
          allElements.add(child);
        } else if (child instanceof JRElementGroup) {
          childElementArray = ((JRElementGroup)child).getElements();
          if (childElementArray != null)
            allElements.addAll(Arrays.asList((Object[])childElementArray)); 
        } 
      } 
      elements = new JRElement[allElements.size()];
      allElements.toArray(elements);
    } 
    return elements;
  }
  
  public JRElement[] getElements() {
    return getElements(this.children);
  }
  
  public static JRElement getElementByKey(JRElement[] elements, String key) {
    JRElement element = null;
    if (key != null)
      if (elements != null) {
        int i = 0;
        while (element == null && i < elements.length) {
          JRElement elem = elements[i];
          if (key.equals(elem.getKey())) {
            element = elem;
          } else if (elem instanceof JRFrame) {
            element = ((JRFrame)elem).getElementByKey(key);
          } else if (elem instanceof JRCrosstab) {
            element = ((JRCrosstab)elem).getElementByKey(key);
          } 
          i++;
        } 
      }  
    return element;
  }
  
  public JRElement getElementByKey(String key) {
    return getElementByKey(getElements(), key);
  }
  
  public void visit(JRVisitor visitor) {
    visitor.visitElementGroup(this);
  }
  
  public Object clone() {
    JRBaseElementGroup clone = null;
    try {
      clone = (JRBaseElementGroup)super.clone();
    } catch (CloneNotSupportedException e) {
      throw new JRRuntimeException(e);
    } 
    if (this.children != null) {
      clone.children = new ArrayList(this.children.size());
      for (int i = 0; i < this.children.size(); i++)
        clone.children.add(((JRChild)this.children.get(i)).clone(clone)); 
    } 
    return clone;
  }
  
  public Object clone(JRElementGroup parentGroup) {
    JRBaseElementGroup clone = (JRBaseElementGroup)clone();
    clone.elementGroup = parentGroup;
    return clone;
  }
}
