/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.ode.bpel.compiler;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.wsdl.Definition;
import javax.wsdl.Import;
import javax.wsdl.Message;
import javax.wsdl.PortType;
import javax.wsdl.Types;
import javax.wsdl.extensions.ExtensibilityElement;
import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.ode.bpel.compiler.api.CompilationException;
import org.apache.ode.bpel.compiler.api.CompilerContext;
import org.apache.ode.bpel.compiler.bom.PartnerLinkType;
import org.apache.ode.bpel.compiler.bom.PropertyAlias;
import org.apache.ode.bpel.compiler.wsdl.Definition4BPEL;
import org.apache.ode.bpel.compiler.wsdl.XMLSchemaType;
import org.apache.ode.utils.DOMUtils;
import org.apache.ode.utils.Namespaces;
import org.apache.ode.utils.StreamUtils;
import org.apache.ode.utils.msg.MessageBundle;
import org.apache.ode.utils.xsd.SchemaModel;
import org.apache.ode.utils.xsd.SchemaModelImpl;
import org.apache.ode.utils.xsd.XSUtils;
import org.apache.ode.utils.xsd.XsdException;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;


/**
 * A parsed collection of WSDL definitions, including BPEL-specific extensions.
 */
class WSDLRegistry {
    private static final Logger __log = LoggerFactory.getLogger(WSDLRegistry.class);

    private static final CommonCompilationMessages __cmsgs =
            MessageBundle.getMessages(CommonCompilationMessages.class);

    private final HashMap<String, ArrayList<Definition4BPEL>> _definitions = new HashMap<String, ArrayList<Definition4BPEL>>();

    private final Map<URI, byte[]> _schemas = new HashMap<URI,byte[]>();
    private final Map<URI, byte[]> _internalSchemas = new HashMap<URI, byte[]>();
    private final Map<URI, Document> _documentSchemas = new HashMap<URI, Document>();

    private SchemaModel _model;

    private CompilerContext _ctx;


    WSDLRegistry(CompilerContext cc) {
        // bogus schema to force schema creation
        _schemas.put(URI.create("http://fivesight.com/bogus/namespace"),
                ("<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""
                        + " targetNamespace=\"http://fivesight.com/bogus/namespace\">"
                        + "<xsd:simpleType name=\"__bogusType__\">"
                        + "<xsd:restriction base=\"xsd:normalizedString\"/>"
                        + "</xsd:simpleType>" + "</xsd:schema>").getBytes());
        try {
            _schemas.put(URI.create(Namespaces.WSDL_11), StreamUtils.read(getClass().getResource("/wsdl.xsd")));
            _schemas.put(URI.create("http://www.w3.org/2001/xml.xsd"), StreamUtils.read(getClass().getResource("/xml.xsd")));
        } catch (IOException e) {
            throw new RuntimeException("Couldn't load default schemas.", e);
        }

        _ctx = cc;
    }

    public Definition4BPEL[] getDefinitions(){
        ArrayList<Definition4BPEL> result = new ArrayList<Definition4BPEL>();
        for (ArrayList<Definition4BPEL> definition4BPELs : _definitions.values()) {
            for (Definition4BPEL definition4BPEL : definition4BPELs) {
                result.add(definition4BPEL);
            }
        }
        return result.toArray(new Definition4BPEL[result.size()]);
    }

    /**
     * Get the schema model (XML Schema).
     *
     * @return schema model
     */
    public SchemaModel getSchemaModel() {
        if (_model == null) {
            _model = SchemaModelImpl.newModel(_schemas);
        }
        assert _model != null;
        return _model;
    }

    /**
     * Adds a WSDL definition for use in resolving MessageType, PortType,
     * Operation and BPEL properties and property aliases
     *
     * @param def WSDL definition
     */
    @SuppressWarnings("unchecked")
    public void addDefinition(Definition4BPEL def, ResourceFinder rf, URI defuri) throws CompilationException {
        if (def == null)
            throw new NullPointerException("def=null");

        if (__log.isDebugEnabled()) {
            __log.debug("addDefinition(" + def.getTargetNamespace() + " from " + def.getDocumentBaseURI() + ")");
        }

        if (_definitions.containsKey(def.getTargetNamespace())) {
            // This indicates that we imported a WSDL with the same namespace from
            // two different locations. This is not an error, but should be a warning.
            if (__log.isInfoEnabled()) {
                __log.info("WSDL at " + defuri + " is a duplicate import, your documents " +
                        "should all be in different namespaces (its's not nice but will still work).");
            }
            
            for (Definition4BPEL aDef : _definitions.get(def.getTargetNamespace())) {
                if (aDef.getDocumentBaseURI().equals(def.getDocumentBaseURI())) {
                    if (__log.isInfoEnabled()) {
                        __log.info("WSDL at " + defuri + " is already imported, this denotes a circular reference.");
                        // no need to keep going: either return or throw an error
                    }
                    return;
                }
            }
        }

        ArrayList<Definition4BPEL> defs = null;
        if (_definitions.get(def.getTargetNamespace()) == null) defs = new ArrayList<Definition4BPEL>();
        else defs = _definitions.get(def.getTargetNamespace());

        defs.add(def);
        _definitions.put(def.getTargetNamespace(), defs);

        captureSchemas(def, rf, defuri);

        if (__log.isDebugEnabled())
            __log.debug("Processing <imports> in " + def.getDocumentBaseURI());

        for (List<Import>  imports : ((Map<String, List<Import>>)def.getImports()).values()) {
            HashSet<String> imported = new HashSet<String>();

            for (Import im : imports) {
                // If there are several imports in the same WSDL all importing the same namespace
                // that is a sure sign of programmer error.
                if (imported.contains(im.getNamespaceURI())) {
                    if (__log.isInfoEnabled()) {
                        __log.info("WSDL at " + im.getLocationURI() + " imports several documents in the same " +
                                "namespace (" + im.getNamespaceURI() + "), your documents should all be in different " +
                                "namespaces (its's not nice but will still work).");
                    }
                }

                Definition4BPEL importDef = (Definition4BPEL) im.getDefinition();

                // The assumption here is that if the definition is not set on the
                // import object then there was some problem parsing the thing,
                // although it would have been nice to actually get the parse
                // error.
                if (importDef == null) {
                    CompilationException ce = new CompilationException(
                            __cmsgs.errWsdlImportNotFound(im.getNamespaceURI(),
                                    im.getLocationURI()).setSource(new SourceLocationImpl(defuri)));
                    if (_ctx == null)
                        throw ce;

                    _ctx.recoveredFromError(new SourceLocationImpl(defuri), ce);
                    continue;
                }

                imported.add(im.getNamespaceURI());
                addDefinition((Definition4BPEL) im.getDefinition(), rf, defuri.resolve(im.getLocationURI()));
            }
        }
    }

    public void addSchemas(Map<URI, byte[]> capture) {
        _schemas.putAll(capture);
    }

    @SuppressWarnings("unchecked")
    private void captureSchemas(Definition def, ResourceFinder rf, URI defuri) throws CompilationException {
        assert def != null;

        if (__log.isDebugEnabled())
            __log.debug("Processing XSD schemas in " + def.getDocumentBaseURI());

        Types types = def.getTypes();

        if (types != null) {
            addAllInternalSchemas(def);

            int localSchemaId = 0;
            for (Iterator<ExtensibilityElement> iter =
                    ((List<ExtensibilityElement>)def.getTypes().getExtensibilityElements()).iterator();
                 iter.hasNext();) {
                ExtensibilityElement ee = iter.next();

                if (ee instanceof XMLSchemaType) {
                    byte[] schema = ((XMLSchemaType)ee).getXMLSchema();
                    WsdlFinderXMLEntityResolver resolver = new WsdlFinderXMLEntityResolver(rf, defuri, _internalSchemas, false);
                    try {
                        Map<URI, byte[]> capture = XSUtils.captureSchema(defuri, schema, resolver, localSchemaId);
                        for (URI uri : capture.keySet()) {
                            if (!_schemas.containsKey(uri)) {
                                _schemas.put(uri, capture.get(uri));
                            }
                        }
//                        _schemas.putAll(capture);

                        try {
                            Document doc = DOMUtils.parse(new InputSource(new ByteArrayInputStream(schema)));
                            String schemaTargetNS = doc.getDocumentElement().getAttribute("targetNamespace");
                            if (schemaTargetNS != null && schemaTargetNS.length() > 0) {
                                URI schemaNamespace = new URI(schemaTargetNS);
                                if (!_internalSchemas.containsKey(schemaNamespace)) {
                                    _internalSchemas.put(schemaNamespace, schema);
                                }
                                if (!_documentSchemas.containsKey(schemaNamespace)) {
                                    _documentSchemas.put(schemaNamespace, doc);
                                }
                            }
                        } catch (Exception e) {
                            throw new RuntimeException("Couldn't parse schema in " + def.getTargetNamespace(), e);
                        }
                    } catch (XsdException xsde) {
                        __log.debug("captureSchemas: capture failed for " + defuri,xsde);

                        LinkedList<XsdException> exceptions = new LinkedList<XsdException>();
                        while (xsde != null)  {
                            exceptions.addFirst(xsde);
                            xsde = xsde.getPrevious();
                        }

                        for (XsdException ex : exceptions) {
                            // TODO: the line number here is going to be wrong for the in-line schema.
                            // String location = ex.getSystemId() + ":"  + ex.getLineNumber();
                            CompilationException ce = new CompilationException(
                                    __cmsgs.errSchemaError(ex.getDetailMessage()).setSource(new SourceLocationImpl(defuri)));
                            if (_ctx != null)
                                _ctx.recoveredFromError(new SourceLocationImpl(defuri),ce);
                            else
                                throw ce;
                        }
                    }
                    // invalidate model
                    _model = null;

                    localSchemaId ++;
                }
            }
        }
    }

    @SuppressWarnings("unchecked")
    private void addAllInternalSchemas(Definition def) {
        for (Iterator<ExtensibilityElement> iter = ((List<ExtensibilityElement>) def.getTypes().getExtensibilityElements()).iterator(); iter.hasNext();) {
            ExtensibilityElement ee = iter.next();

            if (ee instanceof XMLSchemaType) {
                byte[] schema = ((XMLSchemaType) ee).getXMLSchema();
                try {
                    Document doc = DOMUtils.parse(new InputSource(new ByteArrayInputStream(schema)));
                    String schemaTargetNS = doc.getDocumentElement().getAttribute("targetNamespace");
                    if (schemaTargetNS != null && schemaTargetNS.length() > 0) {
                        _internalSchemas.put(new URI(schemaTargetNS), schema);
                        _documentSchemas.put(new URI(schemaTargetNS), doc);
                    }
                } catch (Exception e) {
                    throw new RuntimeException("Couldn't parse schema in " + def.getTargetNamespace(), e);
                }
            }
        }
    }

    public org.apache.ode.bpel.compiler.bom.Property getProperty(QName name) {
        ArrayList<Definition4BPEL> defs = _definitions.get(name.getNamespaceURI());
        if (defs == null) return null;
        for (Definition4BPEL definition4BPEL : defs) {
            if (definition4BPEL != null && definition4BPEL.getProperty(name) != null)
                return definition4BPEL.getProperty(name);
        }
        return null;
    }

    public PropertyAlias getPropertyAlias(QName propertyName, QName messageType) {
        ArrayList<Definition4BPEL> defs = _definitions.get(propertyName.getNamespaceURI());
        if (defs == null) return null;
        for (Definition4BPEL definition4BPEL : defs) {
            if (definition4BPEL != null && definition4BPEL.getPropertyAlias(propertyName, messageType) != null)
                return definition4BPEL.getPropertyAlias(propertyName, messageType);
        }
        return null;
    }

    public PartnerLinkType getPartnerLinkType(QName partnerLinkType) {
        ArrayList<Definition4BPEL> defs = _definitions.get(partnerLinkType.getNamespaceURI());
        if (defs == null) return null;
        for (Definition4BPEL definition4BPEL : defs) {
            if (definition4BPEL != null && definition4BPEL.getPartnerLinkType(partnerLinkType) != null)
                return definition4BPEL.getPartnerLinkType(partnerLinkType);
        }
        return null;
    }

    public PortType getPortType(QName portType) {
        ArrayList<Definition4BPEL> defs = _definitions.get(portType.getNamespaceURI());
        if (defs == null) return null;
        for (Definition4BPEL definition4BPEL : defs) {
            if (definition4BPEL != null && definition4BPEL.getPortType(portType) != null)
                return definition4BPEL.getPortType(portType);
        }
        return null;
    }

    public Message getMessage(QName msgType) {
        ArrayList<Definition4BPEL> defs = _definitions.get(msgType.getNamespaceURI());
        if (defs == null) return null;
        for (Definition4BPEL definition4BPEL : defs) {
            if (definition4BPEL != null && definition4BPEL.getMessage(msgType) != null)
                return definition4BPEL.getMessage(msgType);
        }
        return null;
    }

    /**
     * @return All parsed schemas. This doesn't include schemas from bpel imports.
     */
    Map<URI, Document> getSchemaDocuments() {
        return _documentSchemas;
    }

    /**
     * @return All captured schema sources including those from bpel imports.
     */
    Map<URI, Source> getSchemaSources() {
        Map<URI, Source> schemaSources = new HashMap<URI, Source>();
        for (URI uri : _documentSchemas.keySet()) {
            Document document = _documentSchemas.get(uri);
            schemaSources.put(uri, new DOMSource(document));
        }

        for (URI uri : _schemas.keySet()) {
            schemaSources.put(uri, new StreamSource(new ByteArrayInputStream(_schemas.get(uri))));
        }

        return schemaSources;
    }
}
