/*
 * Copyright 2000-2009 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.intellij.uiDesigner.lw;

import com.intellij.uiDesigner.UIFormXmlConstants;
import com.intellij.uiDesigner.compiler.UnexpectedFormElementException;
import com.intellij.uiDesigner.core.GridLayoutManager;
import com.intellij.uiDesigner.shared.BorderType;
import com.intellij.uiDesigner.shared.XYLayoutManager;
import org.jdom.Element;

import java.awt.*;
import java.util.ArrayList;
import java.util.Iterator;

/**
 * @author Anton Katilin
 * @author Vladimir Kondratyev
 */
public class LwContainer extends LwComponent implements IContainer{
  // PLEASE DO NOT USE GENERICS IN THIS FILE AS IT IS USED IN JAVAC2 ANT TASK THAT SHOULD BE RUNNABLE WITH JDK 1.3

  /**
   * Children components
   */
  private final ArrayList myComponents;
  /**
   * Describes border's type. This member is never <code>null</code>
   */
  private BorderType myBorderType;
  /**
   * Border's title. If border doesn't have any title then
   * this member is <code>null</code>.
   */
  private StringDescriptor myBorderTitle;
  private int myBorderTitleJustification;
  private int myBorderTitlePosition;
  private FontDescriptor myBorderTitleFont;
  private ColorDescriptor myBorderTitleColor;
  private Insets myBorderSize;
  private ColorDescriptor myBorderColor;
  private LayoutManager myLayout;
  private String myLayoutManager;
  protected LayoutSerializer myLayoutSerializer;

  public LwContainer(final String className){
    super(className);
    myComponents = new ArrayList();

    // By default container doesn't have any special border
    setBorderType(BorderType.NONE);

    myLayout = createInitialLayout();
  }


  protected LayoutManager createInitialLayout(){
    return new XYLayoutManager();
  }

  public final LayoutManager getLayout() {
    return myLayout;
  }

  public final void setLayout(final LayoutManager layout) {
    myLayout = layout;
  }

  public String getLayoutManager() {
    return myLayoutManager;
  }

  public final boolean isGrid(){
    return getLayout() instanceof GridLayoutManager;
  }

  public final boolean isXY(){
    return getLayout() instanceof XYLayoutManager;
  }

  /**
   * @param component component to be added.
   *
   * @exception IllegalArgumentException if <code>component</code> is <code>null</code>
   * @exception IllegalArgumentException if <code>component</code> already exist in the
   * container
   */
  public final void addComponent(final LwComponent component){
    if (component == null) {
      throw new IllegalArgumentException("component cannot be null");
    }
    if (myComponents.contains(component)) {
      throw new IllegalArgumentException("component is already added: " + component);
    }
    if (component.getParent() != null) {
      throw new IllegalArgumentException("component already added to another container");
    }

    // Attach to new parent
    myComponents.add(component);
    component.setParent(this);
  }

  public final IComponent getComponent(final int index) {
    return (IComponent)myComponents.get(index);
  }

  public final int getComponentCount() {
    return myComponents.size();
  }

  public int indexOfComponent(final IComponent lwComponent) {
    return myComponents.indexOf(lwComponent);
  }

  /**
   * @return border's type. The method never return <code>null</code>.
   *
   * @see BorderType
   */
  public final BorderType getBorderType(){
    return myBorderType;
  }

  public boolean accept(ComponentVisitor visitor) {
    if (!super.accept(visitor)) {
      return false;
    }

    for (int i = 0; i < getComponentCount(); i++) {
      final IComponent c = getComponent(i);
      if (!c.accept(visitor)) {
        return false;
      }
    }

    return true;
  }

  /**
   * @see BorderType
   *
   * @exception IllegalArgumentException if <code>type</code>
   * is <code>null</code>
   */
  public final void setBorderType(final BorderType type){
    if(type==null){
      throw new IllegalArgumentException("type cannot be null");
    }
    myBorderType=type;
  }

  /**
   * @return border's title. If the container doesn't have any title then the
   * method returns <code>null</code>.
   */
  public final StringDescriptor getBorderTitle(){
    return myBorderTitle;
  }

  /**
   * @param title new border's title. <code>null</code> means that
   * the containr doesn't have have titled border.
   */
  public final void setBorderTitle(final StringDescriptor title){
    myBorderTitle=title;
  }

  public int getBorderTitleJustification() {
    return myBorderTitleJustification;
  }

  public int getBorderTitlePosition() {
    return myBorderTitlePosition;
  }

  public FontDescriptor getBorderTitleFont() {
    return myBorderTitleFont;
  }

  public ColorDescriptor getBorderTitleColor() {
    return myBorderTitleColor;
  }

  public Insets getBorderSize() {
    return myBorderSize;
  }

  public ColorDescriptor getBorderColor() {
    return myBorderColor;
  }

  /**
   * TODO[anton,vova] looks like it is better to pass contraints tag
   * 
   * @param element XML element which should contains 'constraints' tag
   */
  protected void readConstraintsForChild(final Element element, final LwComponent component){
    if (myLayoutSerializer != null) {
      final Element constraintsElement = LwXmlReader.getRequiredChild(element, "constraints");
      myLayoutSerializer.readChildConstraints(constraintsElement, component);
    }
  }

  /**
   * 'border' is required subtag
   */
  protected final void readBorder(final Element element) {
    final Element borderElement = LwXmlReader.getRequiredChild(element, UIFormXmlConstants.ELEMENT_BORDER);
    setBorderType(BorderType.valueOf(LwXmlReader.getRequiredString(borderElement, UIFormXmlConstants.ATTRIBUTE_TYPE)));

    StringDescriptor descriptor = LwXmlReader.getStringDescriptor(borderElement,
                                                                  UIFormXmlConstants.ATTRIBUTE_TITLE,
                                                                  UIFormXmlConstants.ATTRIBUTE_TITLE_RESOURCE_BUNDLE,
                                                                  UIFormXmlConstants.ATTRIBUTE_TITLE_KEY);
    if (descriptor != null) {
      setBorderTitle(descriptor);
    }

    myBorderTitleJustification = LwXmlReader.getOptionalInt(borderElement, UIFormXmlConstants.ATTRIBUTE_TITLE_JUSTIFICATION, 0);
    myBorderTitlePosition = LwXmlReader.getOptionalInt(borderElement, UIFormXmlConstants.ATTRIBUTE_TITLE_POSITION, 0);
    Element fontElement = LwXmlReader.getChild(borderElement, UIFormXmlConstants.ELEMENT_FONT);
    if (fontElement != null) {
      myBorderTitleFont = LwXmlReader.getFontDescriptor(fontElement);
    }
    myBorderTitleColor = LwXmlReader.getOptionalColorDescriptor(LwXmlReader.getChild(borderElement, UIFormXmlConstants.ELEMENT_TITLE_COLOR));
    myBorderColor = LwXmlReader.getOptionalColorDescriptor(LwXmlReader.getChild(borderElement, UIFormXmlConstants.ELEMENT_COLOR));
    Element sizeElement = LwXmlReader.getChild(borderElement, UIFormXmlConstants.ELEMENT_SIZE);
    if (sizeElement != null) {
      try {
        myBorderSize = LwXmlReader.readInsets(sizeElement);
      }
      catch(Exception e) {
        myBorderSize = null;
      }
    }
  }

  /**
   * 'children' is required attribute
   */
  protected final void readChildren(final Element element, final PropertiesProvider provider) throws Exception{
    final Element childrenElement = LwXmlReader.getRequiredChild(element, "children");
    for(Iterator i=childrenElement.getChildren().iterator(); i.hasNext();){
      final Element child = (Element)i.next();
      final LwComponent component = createComponentFromTag(child);
      addComponent(component);
      component.read(child, provider);
    }
  }

  public static LwComponent createComponentFromTag(final Element child) throws Exception {
    final String name = child.getName();
    final LwComponent component;
    if("component".equals(name)){
      final String className = LwXmlReader.getRequiredString(child, UIFormXmlConstants.ATTRIBUTE_CLASS);
      component = new LwAtomicComponent(className);
    }
    else if (UIFormXmlConstants.ELEMENT_NESTED_FORM.equals(name)) {
      component = new LwNestedForm();
    }
    else if("vspacer".equals(name)){
      component = new LwVSpacer();
    }
    else if("hspacer".equals(name)){
      component = new LwHSpacer();
    }
    else if("xy".equals(name) || "grid".equals(name)){
      String className = LwXmlReader.getOptionalString(child, UIFormXmlConstants.ATTRIBUTE_CLASS, "javax.swing.JPanel");
      component = new LwContainer(className);
    }
    else if(UIFormXmlConstants.ELEMENT_SCROLLPANE.equals(name)) {
      String className = LwXmlReader.getOptionalString(child, UIFormXmlConstants.ATTRIBUTE_CLASS, "javax.swing.JScrollPane");
      component = new LwScrollPane(className);
    }
    else if(UIFormXmlConstants.ELEMENT_TABBEDPANE.equals(name)){
      String className = LwXmlReader.getOptionalString(child, UIFormXmlConstants.ATTRIBUTE_CLASS, "javax.swing.JTabbedPane");
      component = new LwTabbedPane(className);
    }
    else if(UIFormXmlConstants.ELEMENT_SPLITPANE.equals(name)){
      String className = LwXmlReader.getOptionalString(child, UIFormXmlConstants.ATTRIBUTE_CLASS, "javax.swing.JSplitPane");
      component = new LwSplitPane(className);
    }
    else if (UIFormXmlConstants.ELEMENT_TOOLBAR.equals(name)) {
      String className = LwXmlReader.getOptionalString(child, UIFormXmlConstants.ATTRIBUTE_CLASS, "javax.swing.JToolBar");
      component = new LwToolBar(className);
    }
    else{
      throw new UnexpectedFormElementException("unexpected element: "+child);
    }
    return component;
  }

  /**
   * 'xy' or 'grid'
   */
  protected final void readLayout(final Element element){
    myLayoutManager = element.getAttributeValue("layout-manager");
    if("xy".equals(element.getName())){
      myLayoutSerializer = XYLayoutSerializer.INSTANCE;
    }
    else if("grid".equals(element.getName())){
      createLayoutSerializer();
    }
    else{
      throw new UnexpectedFormElementException("unexpected element: "+element);
    }
    myLayoutSerializer.readLayout(element, this);
  }

  public void setLayoutManager(final String layoutManager) {
    myLayoutManager = layoutManager;
    createLayoutSerializer();
  }

  private void createLayoutSerializer() {
    if (UIFormXmlConstants.LAYOUT_BORDER.equals(myLayoutManager)) {
      myLayoutSerializer = BorderLayoutSerializer.INSTANCE;
    }
    else if (UIFormXmlConstants.LAYOUT_FLOW.equals(myLayoutManager)) {
      myLayoutSerializer = FlowLayoutSerializer.INSTANCE;
    }
    else if (UIFormXmlConstants.LAYOUT_CARD.equals(myLayoutManager)) {
      myLayoutSerializer = CardLayoutSerializer.INSTANCE;
    }
    else if (UIFormXmlConstants.LAYOUT_XY.equals(myLayoutManager)) {
      myLayoutSerializer = XYLayoutSerializer.INSTANCE;
    }
    else if (UIFormXmlConstants.LAYOUT_FORM.equals(myLayoutManager)) {
      myLayoutSerializer = FormLayoutSerializer.INSTANCE;
    }
    else if (UIFormXmlConstants.LAYOUT_GRIDBAG.equals(myLayoutManager)) {
      myLayoutSerializer = GridBagLayoutSerializer.INSTANCE;      
    }
    else {
      myLayoutSerializer = GridLayoutSerializer.INSTANCE;
    }
  }

  public void read(final Element element, final PropertiesProvider provider) throws Exception {
    readBase(element);

    // Layout
    readLayout(element);

    // Constraints and properties
    readConstraints(element);
    readProperties(element, provider);

    // Border
    readBorder(element);

    readChildren(element, provider);
  }

  protected void readNoLayout(final Element element, final PropertiesProvider provider) throws Exception {
    readBase(element);

    // Constraints and properties
    readConstraints(element);
    readProperties(element, provider);

    // Border
    readBorder(element);

    readChildren(element, provider);
  }

  public boolean areChildrenExclusive() {
    return UIFormXmlConstants.LAYOUT_CARD.equals(myLayoutManager);
  }
}