/*******************************************************************************
 * 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(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");
        
        if (!spec.getTagPath().equals("BUILT_IN_SIMPLE_TYPE")) {
            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;
    }

}