/*
 * 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.axis2.jaxbri;

import com.sun.codemodel.JCodeModel;
import com.sun.codemodel.writer.FileCodeWriter;
import com.sun.tools.xjc.api.ErrorListener;
import com.sun.tools.xjc.api.Mapping;
import com.sun.tools.xjc.api.Property;
import com.sun.tools.xjc.api.S2JJAXBModel;
import com.sun.tools.xjc.api.SchemaCompiler;
import com.sun.tools.xjc.api.XJC;
import com.sun.tools.xjc.BadCommandLineException;
import org.apache.axis2.description.AxisMessage;
import org.apache.axis2.description.AxisOperation;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.util.SchemaUtil;
import org.apache.axis2.util.URLProcessor;
import org.apache.axis2.util.XMLUtils;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.axis2.wsdl.WSDLUtil;
import org.apache.axis2.wsdl.codegen.CodeGenConfiguration;
import org.apache.axis2.wsdl.databinding.DefaultTypeMapper;
import org.apache.axis2.wsdl.databinding.JavaTypeMapper;
import org.apache.axis2.wsdl.databinding.TypeMapper;
import org.apache.axis2.wsdl.util.Constants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.commons.schema.XmlSchema;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import javax.xml.namespace.QName;
import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
import java.util.*;
import java.net.URLClassLoader;
import java.net.URL;

public class CodeGenerationUtility {
    private static final Log log = LogFactory.getLog(CodeGenerationUtility.class);

    public static final String BINDING_FILE_NAME = "bindingFileName";

    /**
     * @param additionalSchemas
     * @throws RuntimeException
     */
    public static TypeMapper processSchemas(final List schemas,
                                            Element[] additionalSchemas,
                                            CodeGenConfiguration cgconfig)
            throws RuntimeException {
        try {

            //check for the imported types. Any imported types are supposed to be here also
            if (schemas == null || schemas.isEmpty()) {
                //there are no types to be code generated
                //However if the type mapper is left empty it will be a problem for the other
                //processes. Hence the default type mapper is set to the configuration
                return new DefaultTypeMapper();
            }

            final Map schemaToInputSourceMap = new HashMap();

            //create the type mapper
            JavaTypeMapper mapper = new JavaTypeMapper();

            String baseURI = cgconfig.getBaseURI();
            if (!baseURI.endsWith("/")){
               baseURI = baseURI + "/";
            }


            for (int i = 0; i < schemas.size(); i++) {
                XmlSchema schema = (XmlSchema)schemas.get(i);
                InputSource inputSource =
                        new InputSource(new StringReader(getSchemaAsString(schema)));
                //here we have to set a proper system ID. otherwise when processing the
                // included schaemas for this schema we have a problem
                // it creates the system ID using this target namespace value

                inputSource.setSystemId(baseURI + "xsd" + i + ".xsd");
                inputSource.setPublicId(schema.getTargetNamespace());
                schemaToInputSourceMap.put(schema,inputSource);
            }

            File outputDir = new File(cgconfig.getOutputLocation(), "src");
            outputDir.mkdir();

            Map nsMap = cgconfig.getUri2PackageNameMap();
            EntityResolver resolver = new EntityResolver() {
                public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
                    InputSource returnInputSource = null;
                    XmlSchema key = null;
                    for (Iterator iter = schemaToInputSourceMap.keySet().iterator();iter.hasNext();) {
                        key = (XmlSchema) iter.next();
                        String nsp = key.getTargetNamespace();
                        if (nsp != null && nsp.equals(publicId)) {

                            // when returning the input stream we have to always return a new
                            // input stream.
                            // sinc jaxbri internally consumes the input stream it gives an
                            // exception.
                            returnInputSource = new InputSource(new StringReader(getSchemaAsString(key)));
                            InputSource existingInputSource = (InputSource) schemaToInputSourceMap.get(key);
                            returnInputSource.setSystemId(existingInputSource.getSystemId());
                            returnInputSource.setPublicId(existingInputSource.getPublicId());
                            break;
                        }
                    }
                    if (returnInputSource == null){
                        // then we have to find this using the file system
                        if (systemId != null){
                            returnInputSource = new InputSource(systemId);
                            returnInputSource.setSystemId(systemId);
                        }
                    }
                    return returnInputSource;
                }
            };


            Map properties = cgconfig.getProperties();
            String bindingFileName = (String) properties.get(BINDING_FILE_NAME);

            XmlSchema key = null;
            for (Iterator schemaIter = schemaToInputSourceMap.keySet().iterator();
                 schemaIter.hasNext();) {

                SchemaCompiler sc = XJC.createSchemaCompiler();
                if (bindingFileName != null){
                    if (bindingFileName.endsWith(".jar")) {
                        scanEpisodeFile(new File(bindingFileName), sc);
                    } else {
                        InputSource inputSoruce = new InputSource(new FileInputStream(bindingFileName));
                        inputSoruce.setSystemId(new File(bindingFileName).toURI().toString());
                        sc.getOptions().addBindFile(inputSoruce);
                    }

                }

                key = (XmlSchema) schemaIter.next();

                if (nsMap != null) {
                    Iterator iterator = nsMap.entrySet().iterator();
                    while(iterator.hasNext()){
                        Map.Entry entry = (Map.Entry) iterator.next();
                        String namespace = (String) entry.getKey();
                        String pkg = (String)nsMap.get(namespace);
                        registerNamespace(sc, namespace, pkg);
                    }
                }

                sc.setEntityResolver(resolver);

                sc.setErrorListener(new ErrorListener(){
                    public void error(SAXParseException saxParseException) {
                        log.error(saxParseException.getMessage());
                        log.debug(saxParseException.getMessage(), saxParseException);
                    }

                    public void fatalError(SAXParseException saxParseException) {
                        log.error(saxParseException.getMessage());
                        log.debug(saxParseException.getMessage(), saxParseException);
                    }

                    public void warning(SAXParseException saxParseException) {
                        log.warn(saxParseException.getMessage());
                        log.debug(saxParseException.getMessage(), saxParseException);
                    }

                    public void info(SAXParseException saxParseException) {
                        log.info(saxParseException.getMessage());
                        log.debug(saxParseException.getMessage(), saxParseException);
                    }
                });

                sc.parseSchema((InputSource) schemaToInputSourceMap.get(key));

                // Bind the XML
                S2JJAXBModel jaxbModel = sc.bind();

                if(jaxbModel == null){
                    throw new RuntimeException("Unable to generate code using jaxbri");
                }

                // Emit the code artifacts
                JCodeModel codeModel = jaxbModel.generateCode(null, null);
                FileCodeWriter writer = new FileCodeWriter(outputDir);
                codeModel.build(writer);

                Collection mappings = jaxbModel.getMappings();

                Iterator iter = mappings.iterator();

                while (iter.hasNext()) {
                    Mapping mapping = (Mapping)iter.next();
                    QName qn = mapping.getElement();
                    String typeName = mapping.getType().getTypeClass().fullName();

                    mapper.addTypeMappingName(qn, typeName);
                }

                //process the unwrapped parameters
                if (!cgconfig.isParametersWrapped()) {
                    //figure out the unwrapped operations
                    List axisServices = cgconfig.getAxisServices();
                    for (Iterator servicesIter = axisServices.iterator(); servicesIter.hasNext();) {
                        AxisService axisService = (AxisService)servicesIter.next();
                        for (Iterator operations = axisService.getOperations();
                             operations.hasNext();) {
                            AxisOperation op = (AxisOperation)operations.next();

                            if (WSDLUtil.isInputPresentForMEP(op.getMessageExchangePattern())) {
                                AxisMessage message = op.getMessage(
                                        WSDLConstants.MESSAGE_LABEL_IN_VALUE);
                                if (message != null &&
                                        message.getParameter(Constants.UNWRAPPED_KEY) != null) {

                                    Mapping mapping = jaxbModel.get(message.getElementQName());
                                    List elementProperties = mapping.getWrapperStyleDrilldown();
                                    for(int j = 0; j < elementProperties.size(); j++){
                                        Property elementProperty = (Property) elementProperties.get(j);

                                        QName partQName =
                                                    WSDLUtil.getPartQName(op.getName().getLocalPart(),
                                                                          WSDLConstants.INPUT_PART_QNAME_SUFFIX,
                                                                          elementProperty.elementName().getLocalPart());
                                        //this type is based on a primitive type- use the
                                        //primitive type name in this case
                                        String fullJaveName =
                                                elementProperty.type().fullName();
                                        if (elementProperty.type().isArray()) {
                                            fullJaveName = fullJaveName.concat("[]");
                                        }
                                        mapper.addTypeMappingName(partQName, fullJaveName);

                                        if (elementProperty.type().isPrimitive()) {
                                            mapper.addTypeMappingStatus(partQName, Boolean.TRUE);
                                        }
                                        if (elementProperty.type().isArray()) {
                                            mapper.addTypeMappingStatus(partQName,
                                                                        Constants.ARRAY_TYPE);
                                        }
                                    }
                                }
                            }

                            if (WSDLUtil.isOutputPresentForMEP(op.getMessageExchangePattern())) {
                                AxisMessage message = op.getMessage(
                                        WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
                                if (message != null &&
                                        message.getParameter(Constants.UNWRAPPED_KEY) != null) {

                                    Mapping mapping = jaxbModel.get(message.getElementQName());
                                    List elementProperties = mapping.getWrapperStyleDrilldown();
                                    for(int j = 0; j < elementProperties.size(); j++){
                                        Property elementProperty = (Property) elementProperties.get(j);

                                        QName partQName =
                                                    WSDLUtil.getPartQName(op.getName().getLocalPart(),
                                                                          WSDLConstants.OUTPUT_PART_QNAME_SUFFIX,
                                                                          elementProperty.elementName().getLocalPart());
                                        //this type is based on a primitive type- use the
                                        //primitive type name in this case
                                        String fullJaveName =
                                                elementProperty.type().fullName();
                                        if (elementProperty.type().isArray()) {
                                            fullJaveName = fullJaveName.concat("[]");
                                        }
                                        mapper.addTypeMappingName(partQName, fullJaveName);

                                        if (elementProperty.type().isPrimitive()) {
                                            mapper.addTypeMappingStatus(partQName, Boolean.TRUE);
                                        }
                                        if (elementProperty.type().isArray()) {
                                            mapper.addTypeMappingStatus(partQName,
                                                                        Constants.ARRAY_TYPE);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // Return the type mapper
            return mapper;

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static void scanEpisodeFile(File jar, SchemaCompiler sc)
            throws BadCommandLineException, IOException {

        URLClassLoader ucl = new URLClassLoader(new URL[]{jar.toURL()});
        Enumeration<URL> resources = ucl.findResources("META-INF/sun-jaxb.episode");
        while (resources.hasMoreElements()) {
            URL url = resources.nextElement();
            sc.getOptions().addBindFile(new InputSource(url.toExternalForm()));
        }

    }


    private static void registerNamespace(SchemaCompiler sc, String namespace, String pkgName) throws Exception {
        Document doc = XMLUtils.newDocument();
        Element rootElement = doc.createElement("schema");
        rootElement.setAttribute("xmlns", "http://www.w3.org/2001/XMLSchema");
        rootElement.setAttribute("xmlns:jaxb", "http://java.sun.com/xml/ns/jaxb");
        rootElement.setAttribute("jaxb:version", "2.0");
        rootElement.setAttribute("targetNamespace", namespace);
        Element annoElement = doc.createElement("annotation");
        Element appInfo = doc.createElement("appinfo");
        Element schemaBindings = doc.createElement("jaxb:schemaBindings");
        Element pkgElement = doc.createElement("jaxb:package");
        pkgElement.setAttribute("name", pkgName);
        annoElement.appendChild(appInfo);
        appInfo.appendChild(schemaBindings);
        schemaBindings.appendChild(pkgElement);
        rootElement.appendChild(annoElement);
        File file = File.createTempFile("customized",".xsd");
        FileOutputStream stream = new FileOutputStream(file);
        try {
            Result result = new StreamResult(stream);
            Transformer xformer = TransformerFactory.newInstance().newTransformer();
            xformer.transform(new DOMSource(rootElement), result);
            stream.flush();
            stream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        InputSource ins = new InputSource(file.toURI().toString());
        sc.parseSchema(ins);
        file.delete();
    }

    private static String extractNamespace(XmlSchema schema) {
        String pkg;
        pkg = schema.getTargetNamespace();
        if (pkg == null) {
            XmlSchema[] schemas2 = SchemaUtil.getAllSchemas(schema);
            for (int j = 0; schemas2 != null && j < schemas2.length; j++) {
                pkg = schemas2[j].getTargetNamespace();
                if (pkg != null)
                    break;
            }
        }
        if (pkg == null) {
            pkg = URLProcessor.DEFAULT_PACKAGE;
        }
        pkg = URLProcessor.makePackageName(pkg);
        return pkg;
    }

    private static String getSchemaAsString(XmlSchema schema) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        schema.write(baos);
        return baos.toString();
    }
}