/*******************************************************************************
 * Copyright (c) 2001, 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.wst.xsd.ui.internal.actions;

import java.util.ArrayList;
import java.util.Iterator;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.wst.sse.core.internal.format.IStructuredFormatProcessor;
import org.eclipse.wst.xml.core.internal.document.DocumentImpl;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
import org.eclipse.wst.xml.core.internal.provisional.format.FormatProcessorXML;
import org.eclipse.wst.xsd.ui.internal.XSDEditorPlugin;
import org.eclipse.wst.xsd.ui.internal.util.TypesHelper;
import org.eclipse.wst.xsd.ui.internal.util.XSDDOMHelper;
import org.eclipse.wst.xsd.ui.internal.widgets.SetBaseTypeDialog;
import org.eclipse.xsd.XSDComplexTypeDefinition;
import org.eclipse.xsd.XSDConcreteComponent;
import org.eclipse.xsd.XSDSchema;
import org.eclipse.xsd.XSDTypeDefinition;
import org.eclipse.xsd.util.XSDConstants;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;


public class SetBaseTypeAction extends Action
{
  XSDSchema xsdSchema;
  Element element;
  String type = "";
  String derivedByString = "";
  XSDDOMHelper domHelper;
  
  /**
   * Constructor for SetBaseTypeAction.
   */
  public SetBaseTypeAction()
  {
    super();
    domHelper = new XSDDOMHelper();
  }
  /**
   * Constructor for SetBaseTypeAction.
   * @param arg0
   */
  public SetBaseTypeAction(String arg0)
  {
    super(arg0);
    domHelper = new XSDDOMHelper();
  }
  /**
   * Constructor for SetBaseTypeAction.
   * @param arg0
   * @param arg1
   */
  public SetBaseTypeAction(String arg0, ImageDescriptor arg1)
  {
    super(arg0, arg1);
    domHelper = new XSDDOMHelper();
  }
  /**
   * Constructor for SetBaseTypeAction.
   * @param arg0
   * @param arg1
   */
  public SetBaseTypeAction(String arg0, int arg1)
  {
    super(arg0, arg1);
    domHelper = new XSDDOMHelper();
  }

  
  public void setXSDSchema(XSDSchema schema)
  {
    this.xsdSchema = schema;    
  }

  public void setComplexTypeElement(Element element)
  {
    this.element = element;
  }
  
  public void setType(String type)
  {
    this.type = type; 
  }

  public void setDerivedBy(String derivedByString)
  {
    this.derivedByString = derivedByString;
  }

  public void run()
  {
    Display display = Display.getCurrent();
    // if it is null, get the default one
    display = display == null ? Display.getDefault() : display;
    Shell parentShell = display.getActiveShell();

    SetBaseTypeDialog dialog = new SetBaseTypeDialog(parentShell, xsdSchema, element);
    dialog.setBlockOnOpen(true);

    Element contentModelElement = domHelper.getContentModelFromParent(element);    
    if (contentModelElement != null)
    {
      // to set the current values to show in the dialog
      if (XSDDOMHelper.inputEquals(contentModelElement, XSDConstants.COMPLEXCONTENT_ELEMENT_TAG, false) ||
          XSDDOMHelper.inputEquals(contentModelElement, XSDConstants.SIMPLECONTENT_ELEMENT_TAG, false))
      {
        Element derivedByElement = domHelper.getDerivedByElementFromComplexType(element);
        if (derivedByElement != null)
        {
          String currentBaseType = derivedByElement.getAttribute(XSDConstants.BASE_ATTRIBUTE);
          dialog.setCurrentBaseType(currentBaseType);
          dialog.setCurrentDerivedBy(derivedByElement.getLocalName());
        }
        else
        {
          dialog.setCurrentBaseType("");
          dialog.setCurrentDerivedBy("");
        }
      }
    }

    int result = dialog.open();
    
    if (result == Window.OK) 
    {
      type = dialog.getBaseType();
      derivedByString = dialog.getDerivedBy();
      performAction();
    }
  }

  XSDTypeDefinition newTypeDefinition = null;
  public XSDTypeDefinition getXSDTypeDefinition()
  {
    return newTypeDefinition;
  }

  public void performAction()
  {
    TypesHelper helper = new TypesHelper(xsdSchema);

    XSDConcreteComponent xsdComp = xsdSchema.getCorrespondingComponent(element);
    
    Element contentModelElement = domHelper.getContentModelFromParent(element);
    boolean contentModelExists = true;
    if (contentModelElement == null)
    {
      contentModelExists = false;
    }

//  get XSD component of the new type chosen
    newTypeDefinition = null;
    for (Iterator i = xsdSchema.getTypeDefinitions().iterator(); i.hasNext(); )
    {
      XSDTypeDefinition typeDef = (XSDTypeDefinition)i.next();
      if (typeDef.getQName().equals(type))
      {
        newTypeDefinition = typeDef;
        break;
      }
    }
   
    boolean needsComplexContent = false;
    boolean needsSimpleContent = false;

    if (helper.getBuiltInTypeNamesList().contains(type) ||
       helper.getUserSimpleTypeNamesList().contains(type))
//    if (newTypeDefinition instanceof XSDSimpleTypeDefinition)
    {
      needsSimpleContent = true; 
    }        
    else if (newTypeDefinition instanceof XSDComplexTypeDefinition)
    {
      needsComplexContent = true;
//      XSDComplexTypeDefinition newCTObj = (XSDComplexTypeDefinition)newTypeDefinition;
//      XSDContentTypeCategory category = newCTObj.getContentTypeCategory();
    }
    
    beginRecording(XSDEditorPlugin.getXSDString("_UI_LABEL_SET_BASE_TYPE"), element);
    String prefix = element.getPrefix();
    prefix = (prefix == null) ? "" : (prefix + ":");

    DOMAttribute attr = new DOMAttribute(XSDConstants.BASE_ATTRIBUTE, type);
    if (!contentModelExists) // if no content model exists, then add the new nodes
    {
      if (helper.getBuiltInTypeNamesList().contains(type) ||
          helper.getUserSimpleTypeNamesList().contains(type))
      {
        updateModelAndDerivedByKind(prefix + XSDConstants.SIMPLECONTENT_ELEMENT_TAG, prefix + XSDConstants.EXTENSION_ELEMENT_TAG, attr);
      }
      else if (helper.getUserComplexTypeNamesList().contains(type))
      {
        if (derivedByString.equals("")) // default
        {
          derivedByString = XSDConstants.EXTENSION_ELEMENT_TAG;
        }
        Element derivedByElement = updateModelAndDerivedByKind(prefix + XSDConstants.COMPLEXCONTENT_ELEMENT_TAG, prefix + derivedByString, attr);
        Element newModelGroupElement = element.getOwnerDocument().createElementNS(XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001, prefix + XSDConstants.SEQUENCE_ELEMENT_TAG);
        derivedByElement.appendChild(newModelGroupElement);
        formatChild(derivedByElement);
      }
    }
    else  // else there is a content model
    {
      if (type.equals(""))  // the chosen type is blank, ie. there is no base type
      {
        Element derivedByElement = domHelper.getDerivedByElementFromComplexType(element);
        Element sourceContentModelElement = domHelper.getContentModelFromParent(derivedByElement);
        // Retain the content model if there is one from the complex or simple content derive by element
        if (XSDDOMHelper.inputEquals(sourceContentModelElement, XSDConstants.SEQUENCE_ELEMENT_TAG, false) ||
            XSDDOMHelper.inputEquals(sourceContentModelElement, XSDConstants.CHOICE_ELEMENT_TAG, false) ||
            XSDDOMHelper.inputEquals(sourceContentModelElement, XSDConstants.ALL_ELEMENT_TAG, false))
        {      
          Element newNode = domHelper.cloneElement(element, sourceContentModelElement);
          element.replaceChild(newNode, contentModelElement);
          formatChild(element); 
        }
        else // otherwise just add the nodes
        {
          XSDDOMHelper.removeNodeAndWhitespace(contentModelElement);
          Element newSequenceElement = element.getOwnerDocument().createElementNS(XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001, prefix + XSDConstants.SEQUENCE_ELEMENT_TAG);
          element.appendChild(newSequenceElement);
          formatChild(newSequenceElement);
        }
      }           
      else // a base type is specified
      {
        Element sequenceChoiceOrAllElement = null;  // copy the model to reposition it off of the new derived by element
        if (XSDDOMHelper.inputEquals(contentModelElement, XSDConstants.SEQUENCE_ELEMENT_TAG, false) ||
            XSDDOMHelper.inputEquals(contentModelElement, XSDConstants.CHOICE_ELEMENT_TAG, false) ||
            XSDDOMHelper.inputEquals(contentModelElement, XSDConstants.ALL_ELEMENT_TAG, false))
        {
           sequenceChoiceOrAllElement = domHelper.cloneElement(element, contentModelElement);
        }

        if (needsComplexContent)
        {
          if (!(XSDDOMHelper.inputEquals(contentModelElement, XSDConstants.COMPLEXCONTENT_ELEMENT_TAG, false)))
          {
            domHelper.changeContentModel(element, XSDConstants.COMPLEXCONTENT_ELEMENT_TAG, sequenceChoiceOrAllElement);
            contentModelElement = domHelper.getContentModelFromParent(element);
          }          
        }
        if (needsSimpleContent)
        {
          if (!(XSDDOMHelper.inputEquals(contentModelElement, XSDConstants.SIMPLECONTENT_ELEMENT_TAG, false)))
          {
            // we don't want to append the element content to a simple content
            sequenceChoiceOrAllElement = null;
            domHelper.changeContentModel(element, XSDConstants.SIMPLECONTENT_ELEMENT_TAG, sequenceChoiceOrAllElement);
            contentModelElement = domHelper.getContentModelFromParent(element);
          }
        }

        Element derivedByElement = domHelper.getDerivedByElementFromComplexType(element);        
        if (derivedByElement == null)
        {
          if (derivedByString == null || (derivedByString != null && derivedByString.equals("")))
          {
            derivedByString = XSDConstants.EXTENSION_ELEMENT_TAG;  // since there is no derivedByElement
          }
          derivedByElement = element.getOwnerDocument().createElementNS(XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001, derivedByString);
          contentModelElement.appendChild(derivedByElement);
          formatChild(contentModelElement);
          if (sequenceChoiceOrAllElement != null)
          {
            derivedByElement.appendChild(sequenceChoiceOrAllElement);
            formatChild(derivedByElement);
          }
        }
        else
        {
          if (helper.getBuiltInTypeNamesList().contains(type) ||
              helper.getUserSimpleTypeNamesList().contains(type))
          {
            derivedByString = XSDConstants.EXTENSION_ELEMENT_TAG;
            Element aContentModelElement = domHelper.getContentModelFromParent(derivedByElement);
            if (aContentModelElement != null)
            {
              XSDDOMHelper.removeNodeAndWhitespace(aContentModelElement);
            }
          }
          domHelper.changeDerivedByType(contentModelElement, derivedByString, type);
        }
        derivedByElement.setAttribute(attr.getName(), attr.getValue());
      }
    }
    
    xsdComp.setElement(element);
    endRecording(element);
  }

  private Element updateModelAndDerivedByKind(String modelType, String derivedByKind, DOMAttribute attr)
  {
    Element newContentModelElement = element.getOwnerDocument().createElementNS(XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001, modelType);
    element.appendChild(newContentModelElement);

    Element newDerivedByElement = element.getOwnerDocument().createElementNS(XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001, derivedByKind);
    newContentModelElement.appendChild(newDerivedByElement);

    newDerivedByElement.setAttribute(attr.getName(), attr.getValue());
    
    NodeList children = element.getChildNodes();
    int length = children.getLength();
    ArrayList nodesToRemove = new ArrayList();
    for (int i = 0; i < length; i++)
    {
      Node node = children.item(i);
      if (XSDDOMHelper.inputEquals(node, XSDConstants.ATTRIBUTE_ELEMENT_TAG, false) ||
          XSDDOMHelper.inputEquals(node, XSDConstants.ATTRIBUTE_ELEMENT_TAG, true) ||
          XSDDOMHelper.inputEquals(node, XSDConstants.ATTRIBUTEGROUP_ELEMENT_TAG, true) ||
          XSDDOMHelper.inputEquals(node, XSDConstants.ANYATTRIBUTE_ELEMENT_TAG, false))
      {
        newDerivedByElement.appendChild(node.cloneNode(true));
        nodesToRemove.add(node);
      }
    }
    for (Iterator i = nodesToRemove.iterator(); i.hasNext(); )
    {
      XSDDOMHelper.removeNodeAndWhitespace((Node)i.next());
    }
    
    formatChild(newContentModelElement);

    return newDerivedByElement;
  }

  protected void formatChild(Element child)
  {
    if (child instanceof IDOMNode)
    {
      IDOMModel model = ((IDOMNode)child).getModel();
      try
      {
        // tell the model that we are about to make a big model change
        model.aboutToChangeModel();
        
        IStructuredFormatProcessor formatProcessor = new FormatProcessorXML();
        formatProcessor.formatNode(child);
      }
      finally
      {
        // tell the model that we are done with the big model change
        model.changedModel(); 
      }
    }

  }

  public DocumentImpl getDocument(Element element)
  {
    return (DocumentImpl) element.getOwnerDocument();
  }

  public void beginRecording(String description, Element element)
  {
    getDocument(element).getModel().beginRecording(this, description);
  }
  
  public void endRecording(Element element)
  {
    DocumentImpl doc = (DocumentImpl) getDocument(element);
    
    doc.getModel().endRecording(this);    
  }
}
