/*
 * 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.wsdl.codegen;

import org.apache.axis2.AxisFault;
import org.apache.axis2.description.WSDL11ToAllAxisServicesBuilder;
import org.apache.axis2.description.WSDL11ToAxisServiceBuilder;
import org.apache.axis2.description.WSDL20ToAllAxisServicesBuilder;
import org.apache.axis2.description.WSDL20ToAxisServiceBuilder;
import org.apache.axis2.util.CommandLineOption;
import org.apache.axis2.util.CommandLineOptionConstants;
import org.apache.axis2.util.CommandLineOptionParser;
import org.apache.axis2.wsdl.codegen.emitter.Emitter;
import org.apache.axis2.wsdl.codegen.extension.CodeGenExtension;
import org.apache.axis2.wsdl.databinding.TypeMapper;
import org.apache.axis2.wsdl.i18n.CodegenMessages;
import org.apache.axis2.wsdl.util.ConfigPropertyFileLoader;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.wsdl.Definition;
import javax.wsdl.WSDLException;
import javax.wsdl.factory.WSDLFactory;
import javax.wsdl.xml.WSDLReader;
import javax.xml.namespace.QName;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class CodeGenerationEngine {

    private static final Log log = LogFactory.getLog(CodeGenerationEngine.class);

    /** Array List for pre-extensions. Extensions that run before the emitter */
    private List preExtensions = new ArrayList();
    /** Array List for post-extensions. Extensions that run after the codegens */
    private List postExtensions = new ArrayList();

    /** Codegen configuration  reference */
    private CodeGenConfiguration configuration;

    /**
     * @param configuration
     * @throws CodeGenerationException
     */
    public CodeGenerationEngine(CodeGenConfiguration configuration) throws CodeGenerationException {
        this.configuration = configuration;
        loadExtensions();
    }

    /**
     * @param parser
     * @throws CodeGenerationException
     */
    public CodeGenerationEngine(CommandLineOptionParser parser) throws CodeGenerationException {
        Map allOptions = parser.getAllOptions();
        String wsdlUri;
        try {

            CommandLineOption option =
                    (CommandLineOption)allOptions.
                            get(CommandLineOptionConstants.WSDL2JavaConstants.WSDL_LOCATION_URI_OPTION);
            wsdlUri = option.getOptionValue();
            configuration = new CodeGenConfiguration(allOptions);


            if (CommandLineOptionConstants.WSDL2JavaConstants.WSDL_VERSION_2.
                    equals(configuration.getWSDLVersion())) {

                WSDL20ToAxisServiceBuilder builder;

                // jibx currently does not support multiservice
                if ((configuration.getServiceName() != null) || (configuration.getDatabindingType().equals("jibx"))) {
                    builder = new WSDL20ToAxisServiceBuilder(
                            wsdlUri,
                            configuration.getServiceName(),
                            configuration.getPortName(),
                            configuration.isAllPorts());
                    builder.setCodegen(true);
                    configuration.addAxisService(builder.populateService());
                } else {
                    builder = new WSDL20ToAllAxisServicesBuilder(wsdlUri, configuration.getPortName());
                    builder.setCodegen(true);
                    builder.setAllPorts(configuration.isAllPorts());
                    configuration.setAxisServices(
                            ((WSDL20ToAllAxisServicesBuilder)builder).populateAllServices());
                }

            } else {
                //It'll be WSDL 1.1
                Definition wsdl4jDef = readInTheWSDLFile(wsdlUri);

                // we save the original wsdl definition to write it to the resource folder later
                // this is required only if it has imports
                Map imports = wsdl4jDef.getImports();
                if ((imports != null) && (imports.size() > 0)) {
                    configuration.setWsdlDefinition(readInTheWSDLFile(wsdlUri));
                } else {
                    configuration.setWsdlDefinition(wsdl4jDef);
                }

                // we generate the code for one service and one port if the
                // user has specified them.
                // otherwise generate the code for every service.
                // TODO: find out a permanant solution for this.
                QName serviceQname = null;

                if (configuration.getServiceName() != null) {
                    serviceQname = new QName(wsdl4jDef.getTargetNamespace(),
                                             configuration.getServiceName());
                }

                WSDL11ToAxisServiceBuilder builder;
                // jibx currently does not support multiservice
                if ((serviceQname != null) || (configuration.getDatabindingType().equals("jibx"))) {
                    builder = new WSDL11ToAxisServiceBuilder(
                            wsdl4jDef,
                            serviceQname,
                            configuration.getPortName(),
                            configuration.isAllPorts());
                    builder.setCodegen(true);
                    configuration.addAxisService(builder.populateService());
                } else {
                    builder = new WSDL11ToAllAxisServicesBuilder(wsdl4jDef, configuration.getPortName());
                    builder.setCodegen(true);
                    builder.setAllPorts(configuration.isAllPorts());
                    configuration.setAxisServices(
                            ((WSDL11ToAllAxisServicesBuilder)builder).populateAllServices());
                }
            }
            configuration.setBaseURI(getBaseURI(wsdlUri));
        } catch (AxisFault axisFault) {
            throw new CodeGenerationException(
                    CodegenMessages.getMessage("engine.wsdlParsingException"), axisFault);
        } catch (WSDLException e) {
            throw new CodeGenerationException(
                    CodegenMessages.getMessage("engine.wsdlParsingException"), e);
        } catch (Exception e) {
            throw new CodeGenerationException(                            
                    CodegenMessages.getMessage("engine.wsdlParsingException"), e);
        }

        loadExtensions();
    }

    /**
     * Loads the relevant preExtensions
     *
     * @throws CodeGenerationException
     */
    private void loadExtensions() throws CodeGenerationException {
        //load pre extensions
        String[] extensions = ConfigPropertyFileLoader.getExtensionClassNames();
        if (extensions != null) {
            for (int i = 0; i < extensions.length; i++) {
                //load the Extension class
                addPreExtension((CodeGenExtension)getObjectFromClassName(extensions[i].trim()));
            }
        }

        //load post extensions
        String[] postExtensions = ConfigPropertyFileLoader.getPostExtensionClassNames();
        if (postExtensions != null) {
            for (int i = 0; i < postExtensions.length; i++) {
                //load the Extension class
                addPostExtension(
                        (CodeGenExtension)getObjectFromClassName(postExtensions[i].trim()));
            }
        }

    }

    /**
     * Adds a given extension to the list
     *
     * @param ext
     */
    private void addPreExtension(CodeGenExtension ext) {
        if (ext != null) {
            preExtensions.add(ext);
        }
    }

    /**
     * Adds a given extension to the list
     *
     * @param ext
     */
    private void addPostExtension(CodeGenExtension ext) {
        if (ext != null) {
            postExtensions.add(ext);
        }
    }

    /**
     * Generate the code!!
     *
     * @throws CodeGenerationException
     */
    public void generate() throws CodeGenerationException {
        try {
            //engage the pre-extensions
            for (int i = 0; i < preExtensions.size(); i++) {
                ((CodeGenExtension)preExtensions.get(i)).engage(configuration);
            }

            Emitter emitter;


            TypeMapper mapper = configuration.getTypeMapper();
            if (mapper == null) {
                // this check is redundant here. The default databinding extension should
                // have already figured this out and thrown an error message. However in case the
                // users decides to mess with the config it is safe to keep this check in order to throw
                // a meaningful error message
                throw new CodeGenerationException(
                        CodegenMessages.getMessage("engine.noProperDatabindingException"));
            }

            //Find and invoke the emitter by reflection
            Map emitterMap = ConfigPropertyFileLoader.getLanguageEmitterMap();
            String className = (String)emitterMap.get(configuration.getOutputLanguage());
            if (className != null) {
                emitter = (Emitter)getObjectFromClassName(className);
                emitter.setCodeGenConfiguration(configuration);
                emitter.setMapper(mapper);
            } else {
                throw new Exception(CodegenMessages.getMessage("engine.emitterMissing"));
            }

            //invoke the necessary methods in the emitter
            if (configuration.isServerSide()) {
                emitter.emitSkeleton();
                // if the users want both client and server, it would be in the
                // generate all option
                if (configuration.isGenerateAll()) {
                    emitter.emitStub();
                }
            } else {
                emitter.emitStub();
            }

            //engage the post-extensions
            for (int i = 0; i < postExtensions.size(); i++) {
                ((CodeGenExtension)postExtensions.get(i)).engage(configuration);
            }

        } catch (ClassCastException e) {
            throw new CodeGenerationException(CodegenMessages.getMessage("engine.wrongEmitter"), e);
        } catch (Exception e) {
            throw new CodeGenerationException(e);
        }


    }


    /**
     * Read the WSDL file
     *
     * @param uri
     * @throws WSDLException
     */
    public Definition readInTheWSDLFile(final String uri) throws WSDLException {

        WSDLReader reader = WSDLFactory.newInstance().newWSDLReader();
        reader.setFeature("javax.wsdl.importDocuments", true);
        return reader.readWSDL(uri);
        
    }


    /**
     * gets a object from the class
     *
     * @param className
     */
    private Object getObjectFromClassName(String className) throws CodeGenerationException {
        try {
            Class extensionClass = getClass().getClassLoader().loadClass(className);
            return extensionClass.newInstance();
        } catch (ClassNotFoundException e) {
            // TODO REVIEW FOR JAVA 6
            // In Java 5, if you passed an array string such as "[Lcom.mypackage.MyClass;" to
            // loadClass, the class would indeed be loaded.  
            // In JDK6, a ClassNotFoundException is thrown. 
            // The work-around is to use code Class.forName instead.
            // Example:
            // try {
            //       classLoader.loadClass(name);
            //  } catch (ClassNotFoundException e) {
            //       Class.forName(name, false, loader);
            //  }
            log.debug(CodegenMessages.getMessage("engine.extensionLoadProblem"), e);
            return null;
        } catch (InstantiationException e) {
            throw new CodeGenerationException(
                    CodegenMessages.getMessage("engine.extensionInstantiationProblem"), e);
        } catch (IllegalAccessException e) {
            throw new CodeGenerationException(CodegenMessages.getMessage("engine.illegalExtension"),
                                              e);
        } catch (NoClassDefFoundError e) {
            log.debug(CodegenMessages.getMessage("engine.extensionLoadProblem"), e);
            return null;
        } catch (Exception e) {
            throw new CodeGenerationException(e);
        }

    }

    /**
     * calculates the base URI Needs improvement but works fine for now ;)
     *
     * @param currentURI
     */
    private String getBaseURI(String currentURI) throws URISyntaxException, IOException {
        File file = new File(currentURI);
        if (file.exists()) {
            return file.getCanonicalFile().getParentFile().toURI().toString();
        }
        String uriFragment = currentURI.substring(0, currentURI.lastIndexOf("/"));
        return uriFragment + (uriFragment.endsWith("/") ? "" : "/");
    }

    /**
     * calculates the URI
     * needs improvement
     *
     * @param currentURI
     */
    private String getURI(String currentURI) throws URISyntaxException, IOException {

        File file = new File(currentURI);
        if (file.exists()){
            return file.getCanonicalFile().toURI().toString();
        } else {
            return currentURI;
        }

    }

    public CodeGenConfiguration getConfiguration() {
        return configuration;
    }
}
