/*******************************************************************************
 * Copyright (c) 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.dialogs.types.xsd;

import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.wst.xml.uriresolver.util.URIHelper;
import org.eclipse.wst.xsd.ui.internal.actions.CreateElementAction;
import org.eclipse.wst.xsd.ui.internal.actions.DOMAttribute;
import org.eclipse.wst.xsd.ui.internal.dialogs.types.xml.XMLComponentSpecification;
import org.eclipse.wst.xsd.ui.internal.refactor.delete.XSDExternalFileCleanup;
import org.eclipse.wst.xsd.ui.internal.util.TypesHelper;
import org.eclipse.wst.xsd.ui.internal.util.XSDDOMHelper;
import org.eclipse.xsd.XSDImport;
import org.eclipse.xsd.XSDInclude;
import org.eclipse.xsd.XSDRedefine;
import org.eclipse.xsd.XSDSchema;
import org.eclipse.xsd.XSDSchemaContent;
import org.eclipse.xsd.XSDSchemaDirective;
import org.eclipse.xsd.util.XSDConstants;
import org.eclipse.xsd.util.XSDParser;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class XSDSetTypeHelper {
    private XSDSchema xsdSchema;
    private IFile currentIFile;
    
    public XSDSetTypeHelper(IFile iFile, XSDSchema schema) {
        currentIFile = iFile;
        xsdSchema = schema;
    }

    public void setType(Element element, String property, XMLComponentSpecification spec) {
        addImportIfNecessary(element, spec);        
        String typeObject = getPrefixedTypeName(spec);
        
        // Get the previous type --> previousStringType
        String previousStringType = "";
        Attr attr = element.getAttributeNode(property);
        if (attr != null) {
            String value = attr.getValue();
        }

        if (!XSDDOMHelper.inputEquals(element, XSDConstants.UNION_ELEMENT_TAG, false))
        {
            if (spec != null && spec.getTagPath().equals("**anonymous**"))
            {
              if (spec.getTagPath().equals("ANONYMOUS_SIMPLE_TYPE"))
              {
                if (!previousStringType.equals("**anonymous**"))
                {
                  updateElementToAnonymous(element, XSDConstants.SIMPLETYPE_ELEMENT_TAG);
                }
              }
              else
              {
                if (!previousStringType.equals("**anonymous**"))
                {
                  updateElementToAnonymous(element, XSDConstants.COMPLEXTYPE_ELEMENT_TAG);
                }
              }
              // element.removeAttribute(XSDConstants.TYPE_ATTRIBUTE);
              element.removeAttribute(property);
            }
            else
            {
              XSDDOMHelper.updateElementToNotAnonymous(element);
              //element.setAttribute(XSDConstants.TYPE_ATTRIBUTE, typeObject.toString());
              element.setAttribute(property, typeObject.toString());
            }
        }
    }
    
    public void addImportIfNecessary(Element element, XMLComponentSpecification spec) {
        String typeObject = "";
        
        // Get the new type --> typeObject
        if (spec != null) {
            String itemType = spec.getTagPath();
            typeObject = (String) spec.getAttributeInfo("name");
            
            if (!itemType.equals("BUILT_IN_SIMPLE_TYPE")) {
                // Do an actual import if needed
                XSDParser parser = new XSDParser();
                parser.parse(spec.getFileLocation());
                XSDSchema schema = parser.getSchema();
                String tns = schema.getTargetNamespace();
                
                boolean exists = false;
                // Check if the type is defined in the 'current' file itself.
                String currentFile = getNormalizedLocation(xsdSchema.getSchemaLocation());
                IPath currentFilePath = new Path(currentFile);
                if (currentFilePath.equals(new Path(spec.getFileLocation()))) {
                    exists = true;
                }

                if (!exists) {
                    if (tns.equals(xsdSchema.getTargetNamespace())) {
                        // Check if the schema is in a redefine/include
                        List existingList = getXSDIncludes();
                        existingList.addAll(getXSDRedefines());
                        Iterator it = existingList.iterator();
                        while (it.hasNext()) {
                            XSDSchemaDirective existingSchema = (XSDSchemaDirective) it.next();
                            String normalizedFile = getNormalizedLocation(existingSchema.getResolvedSchema().getSchemaLocation());
                            String normalizedSpec = spec.getFileLocation();
                            
                            if (normalizedFile.equals(normalizedSpec)) {
                                // Found and existing one
                                exists = true;
                            }
                        }                        
                    }
                    else {
                        // Check if the schema is in a import
                        List existingList = getXSDImports();
                        Iterator it = existingList.iterator();
                        while (it.hasNext()) {
                            XSDSchemaDirective existingSchema = (XSDSchemaDirective) it.next();
                            String normalizedFile = getNormalizedLocation(existingSchema.getResolvedSchema().getSchemaLocation());
                            String normalizedSpec = spec.getFileLocation();

                            if (normalizedFile.equals(normalizedSpec)) {
                                // Found and existing one
                                exists = true;
                            }
                        }                        
                    }
                }
                
                if (!exists) {
                    doImport(spec.getFileLocation(), schema);
                }
            }
        }
    }
    
    /*
     * Return the prefixed type name for the type described by the given
     * XMLComponentSpecification object.
     * If the type described is a Built-in type, do not add the prefix
     */
    public String getPrefixedTypeName(XMLComponentSpecification spec) {
        String typeObject = (String) spec.getAttributeInfo("name");
        
        TypesHelper typesHelper = new TypesHelper(xsdSchema); // ???? Is this correct?
        List prefixedNames = typesHelper.getPrefixedNames(spec.getTargetNamespace(), typeObject);
        if (prefixedNames.size() > 0) {
            // Grab the first prefixed name
            typeObject = (String) prefixedNames.get(0);
        }

        return typeObject;
    }
    
    private void updateElementToAnonymous(Element element, String xsdType) {
        String prefix = element.getPrefix();
        prefix = (prefix == null) ? "" : (prefix + ":");
        XSDDOMHelper.updateElementToNotAnonymous(element);
        boolean hasChildrenElements = hasElementChildren(element);
        Element childNode = null;
        if (xsdType.equals(XSDConstants.COMPLEXTYPE_ELEMENT_TAG)) {
            childNode = element.getOwnerDocument().createElementNS(XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001, prefix + XSDConstants.COMPLEXTYPE_ELEMENT_TAG);
        }
        else if (xsdType.equals(XSDConstants.SIMPLETYPE_ELEMENT_TAG)) {
            childNode = element.getOwnerDocument().createElementNS(XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001, prefix + XSDConstants.SIMPLETYPE_ELEMENT_TAG);
        }
        
        if (childNode != null) {
            XSDDOMHelper helper = new XSDDOMHelper();
            Node annotationNode = helper.getChildNode(element, XSDConstants.ANNOTATION_ELEMENT_TAG);
            if (annotationNode == null) {
                Node firstChild = element.getFirstChild();
                element.insertBefore(childNode, firstChild);
            } else {
                Node nextSibling = annotationNode.getNextSibling();
                element.insertBefore(childNode, nextSibling);
            }
            XSDDOMHelper.formatChild(childNode);
        }
    }

    private boolean hasElementChildren(Node parentNode) {
        boolean hasChildrenElements = false;
        if (parentNode != null && parentNode.hasChildNodes()) {
            NodeList nodes = parentNode.getChildNodes();
            for (int i = 0; i < nodes.getLength(); i++) {
                if (nodes.item(i) instanceof Element) {
                    hasChildrenElements = true;
                    break;
                }
            }
        }
        return hasChildrenElements;
    }

    // TODO: We shouldn't need to pass in IPath externalSchemaPath.
    private void doImport(String externalSchemaPath, XSDSchema externalSchema) {
        // Determine schemaLocation
        String locationAttribute = URIHelper.getRelativeURI(externalSchemaPath, currentIFile.getLocation().toOSString());
        
        boolean isInclude = false;
        if (externalSchema.getTargetNamespace().equals(xsdSchema.getTargetNamespace())) {
            isInclude = true;
        }
        
        if (externalSchema != null) { // In case we have problems loading the file.... we should display an error message.
                Element newElement;
                if (isInclude) {                
                    List attributes = new ArrayList();
                    attributes.add(new DOMAttribute(XSDConstants.SCHEMALOCATION_ATTRIBUTE, locationAttribute));
                    newElement = createElement(XSDConstants.INCLUDE_ELEMENT_TAG, attributes);
                }
                else if (!isInclude) {
                    List attributes = new ArrayList();
                    attributes.add(new DOMAttribute(XSDConstants.NAMESPACE_ATTRIBUTE, externalSchema.getTargetNamespace()));
                    attributes.add(new DOMAttribute(XSDConstants.SCHEMALOCATION_ATTRIBUTE, locationAttribute));
                    newElement = createElement(XSDConstants.IMPORT_ELEMENT_TAG, attributes);
                    handleImportNS(newElement, externalSchema);
                }
        }
    }

    private void handleImportNS(Element importElement, XSDSchema externalSchema) {
        String namespace = externalSchema.getTargetNamespace();
        if (namespace == null) namespace = "";

        XSDImport xsdImport = (XSDImport) xsdSchema.getCorrespondingComponent(importElement);
        xsdImport.setResolvedSchema(externalSchema);
        
        java.util.Map map = xsdSchema.getQNamePrefixToNamespaceMap();
        
//        System.out.println("changed Import Map is " + map.values());
//        System.out.println("changed import Map keys are " + map.keySet());

        // Referential integrity on old import
        // How can we be sure that if the newlocation is the same as the oldlocation
        // the file hasn't changed
        
        XSDSchema referencedSchema = xsdImport.getResolvedSchema();
        if (referencedSchema != null)
        {
          XSDExternalFileCleanup cleanHelper = new XSDExternalFileCleanup(referencedSchema);
          cleanHelper.visitSchema(xsdSchema);
        }

        Element schemaElement = xsdSchema.getElement();

        // update the xmlns in the schema element first, and then update the import element next
        // so that the last change will be in the import element.  This keeps the selection
        // on the import element
        TypesHelper helper = new TypesHelper(externalSchema);
        String prefix = helper.getPrefix(namespace, false);
        
        if (map.containsKey(prefix))
        {
          prefix = null;
        }

        if (prefix == null || (prefix !=null && prefix.length() == 0))
        {
          StringBuffer newPrefix = new StringBuffer("pref");  //$NON-NLS-1$
          int prefixExtension = 1;
          while (map.containsKey(newPrefix.toString()) && prefixExtension < 100)
          {
            newPrefix = new StringBuffer("pref" + String.valueOf(prefixExtension));
            prefixExtension++;
          }
          prefix = newPrefix.toString();
        }

        if (namespace.length() > 0)
        {
          // if ns already in map, use its corresponding prefix
          if (map.containsValue(namespace))
          {
            TypesHelper typesHelper = new TypesHelper(xsdSchema);
            prefix = typesHelper.getPrefix(namespace, false);
          }
          else // otherwise add to the map
          {
            schemaElement.setAttribute("xmlns:"+prefix, namespace);
          }
        }


//        System.out.println("changed Import Map is " + map.values());
//        System.out.println("changed import Map keys are " + map.keySet());
    }
    
    private Element createElement(String elementTag, List attributes) {
        Node relativeNode = XSDDOMHelper.getNextElementNode(xsdSchema.getElement().getFirstChild());
        
        CreateElementAction action = new CreateElementAction("");
        action.setElementTag(elementTag);
        action.setAttributes(attributes);
        action.setParentNode(xsdSchema.getElement());
        action.setRelativeNode(relativeNode);
        action.setXSDSchema(xsdSchema);
        return action.createAndAddNewChildElement();
    }

    private String getNormalizedLocation(String location) {
        try {
            URL url = new URL(location);
            URL resolvedURL = Platform.resolve(url);
            location = resolvedURL.getPath();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        
        return location; 
      }
    
    private List getXSDImports() {
        List imports = new ArrayList();
        
        Iterator contents = xsdSchema.getContents().iterator();
        while (contents.hasNext()) {
            XSDSchemaContent content = (XSDSchemaContent) contents.next();
            if (content instanceof XSDImport) {
                imports.add(content);             
            }
        }
        
        return imports;
    }
    
    private List getXSDIncludes() {
        List includes = new ArrayList();
        
        Iterator contents = xsdSchema.getContents().iterator();
        while (contents.hasNext()) {
            XSDSchemaContent content = (XSDSchemaContent) contents.next();
            if (content instanceof XSDInclude) {
                includes.add(content);            
            }
        }
        
        return includes;
    }

    private List getXSDRedefines() {
        List includes = new ArrayList();
        
        Iterator contents = xsdSchema.getContents().iterator();
        while (contents.hasNext()) {
            XSDSchemaContent content = (XSDSchemaContent) contents.next();
            if (content instanceof XSDRedefine) {
                includes.add(content);            
            }
        }
        
        return includes;
    }

}