/*
 * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.tools.internal.ws.wscompile;

import com.oracle.webservices.internal.api.databinding.WSDLResolver;
import com.sun.tools.internal.ws.ToolVersion;
import com.sun.tools.internal.ws.processor.modeler.annotation.WebServiceAp;
import com.sun.tools.internal.ws.processor.modeler.wsdl.ConsoleErrorReporter;
import com.sun.tools.internal.ws.resources.WscompileMessages;
import com.sun.tools.internal.xjc.util.NullStream;
import com.sun.xml.internal.txw2.TXW;
import com.sun.xml.internal.txw2.TypedXmlWriter;
import com.sun.xml.internal.txw2.annotation.XmlAttribute;
import com.sun.xml.internal.txw2.annotation.XmlElement;
import com.sun.xml.internal.txw2.output.StreamSerializer;
import com.sun.xml.internal.ws.api.BindingID;
import com.sun.xml.internal.ws.api.databinding.DatabindingConfig;
import com.sun.xml.internal.ws.api.databinding.DatabindingFactory;
import com.sun.xml.internal.ws.api.databinding.WSDLGenInfo;
import com.sun.xml.internal.ws.api.server.Container;
import com.sun.xml.internal.ws.api.wsdl.writer.WSDLGeneratorExtension;
import com.sun.xml.internal.ws.binding.WebServiceFeatureList;
import com.sun.xml.internal.ws.model.ExternalMetadataReader;
import com.sun.xml.internal.ws.model.AbstractSEIModelImpl;
import com.sun.xml.internal.ws.util.ServiceFinder;
import org.xml.sax.SAXParseException;

import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import javax.xml.namespace.QName;
import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamResult;
import javax.xml.ws.Holder;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Vivek Pandey
 */

/*
 * All annotation types are supported.
 */
public class WsgenTool {
    private final PrintStream out;
    private final WsgenOptions options = new WsgenOptions();


    public WsgenTool(OutputStream out, Container container) {
        this.out = (out instanceof PrintStream) ? (PrintStream) out : new PrintStream(out);
        this.container = container;
    }


    public WsgenTool(OutputStream out) {
        this(out, null);
    }

    public boolean run(String[] args) {
        final Listener listener = new Listener();
        for (String arg : args) {
            if (arg.equals("-version")) {
                listener.message(
                        WscompileMessages.WSGEN_VERSION(ToolVersion.VERSION.MAJOR_VERSION));
                return true;
            }
            if (arg.equals("-fullversion")) {
                listener.message(
                        WscompileMessages.WSGEN_FULLVERSION(ToolVersion.VERSION.toString()));
                return true;
            }
        }
        try {
            options.parseArguments(args);
            options.validate();
            if (!buildModel(options.endpoint.getName(), listener)) {
                return false;
            }
        } catch (Options.WeAreDone done) {
            usage(done.getOptions());
        } catch (BadCommandLineException e) {
            if (e.getMessage() != null) {
                System.out.println(e.getMessage());
                System.out.println();
            }
            usage(e.getOptions());
            return false;
        } catch (AbortException e) {
            //error might have been reported
        } finally {
            if (!options.keep) {
                options.removeGeneratedFiles();
            }
        }
        return true;
    }

    private final Container container;

    /**
     *
     * @param endpoint
     * @param listener
     * @return
     * @throws BadCommandLineException
     */
    public boolean buildModel(String endpoint, Listener listener) throws BadCommandLineException {
        final ErrorReceiverFilter errReceiver = new ErrorReceiverFilter(listener);

        List<String> args = new ArrayList<>(6 + (options.nocompile ? 1 : 0)
                + (options.encoding != null ? 2 : 0));

        args.add("-d");
        args.add(options.destDir.getAbsolutePath());
        args.add("-classpath");
        args.add(options.classpath);
        args.add("-s");
        args.add(options.sourceDir.getAbsolutePath());
        if (options.nocompile) {
            args.add("-proc:only");
        }
        if (options.encoding != null) {
            args.add("-encoding");
            args.add(options.encoding);
        }

        boolean addModules = true;
        if (options.javacOptions != null) {
            List<String> javacOptions = options.getJavacOptions(args, listener);
            for (int i = 0; i < javacOptions.size(); i++) {
                String opt = javacOptions.get(i);
                if ("-source".equals(opt) && 9 >= getVersion(javacOptions.get(i + 1))) {
                    addModules = false;
                }
                if ("-target".equals(opt) && 9 >= getVersion(javacOptions.get(i + 1))) {
                    addModules = false;
                }
                if ("--release".equals(opt) && 9 >= getVersion(javacOptions.get(i + 1))) {
                    addModules = false;
                }
                args.add(opt);
            }
        }
        if (addModules) {
            args.add("--add-modules");
            args.add("java.xml.ws");
        }

        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        if (compiler == null) {
            out.println(WscompileMessages.WSCOMPILE_CANT_GET_COMPILER(property("java.home"), property("java.version"), property("java.vendor")));
            return false;
        }
        DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
        StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
        JavaCompiler.CompilationTask task = compiler.getTask(
                null,
                fileManager,
                diagnostics,
                args,
                Collections.singleton(endpoint.replaceAll("\\$", ".")),
                null);
        task.setProcessors(Collections.singleton(new WebServiceAp(options, out)));
        boolean result = task.call();

        if (!result) {
            out.println(WscompileMessages.WSCOMPILE_ERROR(WscompileMessages.WSCOMPILE_COMPILATION_FAILED()));
            return false;
        }
        if (options.genWsdl) {
            DatabindingConfig config = new DatabindingConfig();

            List<String> externalMetadataFileNames = options.externalMetadataFiles;
            boolean disableXmlSecurity = options.disableXmlSecurity;
            if (externalMetadataFileNames != null && externalMetadataFileNames.size() > 0) {
                config.setMetadataReader(new ExternalMetadataReader(getExternalFiles(externalMetadataFileNames), null, null, true, disableXmlSecurity));
            }

            String tmpPath = options.destDir.getAbsolutePath() + File.pathSeparator + options.classpath;
            ClassLoader classLoader = new URLClassLoader(Options.pathToURLs(tmpPath),
                    this.getClass().getClassLoader());
            Class<?> endpointClass;
            try {
                endpointClass = classLoader.loadClass(endpoint);
            } catch (ClassNotFoundException e) {
                throw new BadCommandLineException(WscompileMessages.WSGEN_CLASS_NOT_FOUND(endpoint));
            }

            BindingID bindingID = options.getBindingID(options.protocol);
            if (!options.protocolSet) {
                bindingID = BindingID.parse(endpointClass);
            }
            WebServiceFeatureList wsfeatures = new WebServiceFeatureList(endpointClass);
//            RuntimeModeler rtModeler = new RuntimeModeler(endpointClass, options.serviceName, bindingID, wsfeatures.toArray());
//            rtModeler.setClassLoader(classLoader);
            if (options.portName != null)
                config.getMappingInfo().setPortName(options.portName);//rtModeler.setPortName(options.portName);
//            AbstractSEIModelImpl rtModel = rtModeler.buildRuntimeModel();

            DatabindingFactory fac = DatabindingFactory.newInstance();
            config.setEndpointClass(endpointClass);
            config.getMappingInfo().setServiceName(options.serviceName);
            config.setFeatures(wsfeatures.toArray());
            config.setClassLoader(classLoader);
            config.getMappingInfo().setBindingID(bindingID);
            com.sun.xml.internal.ws.db.DatabindingImpl rt = (com.sun.xml.internal.ws.db.DatabindingImpl) fac.createRuntime(config);

            final File[] wsdlFileName = new File[1]; // used to capture the generated WSDL file.
            final Map<String, File> schemaFiles = new HashMap<>();

            WSDLGenInfo wsdlGenInfo = new WSDLGenInfo();
            wsdlGenInfo.setSecureXmlProcessingDisabled(disableXmlSecurity);

            wsdlGenInfo.setWsdlResolver(
                    new WSDLResolver() {
                        private File toFile(String suggestedFilename) {
                            return new File(options.nonclassDestDir, suggestedFilename);
                        }

                        private Result toResult(File file) {
                            Result result;
                            try {
                                result = new StreamResult(new FileOutputStream(file));
                                result.setSystemId(file.getPath().replace('\\', '/'));
                            } catch (FileNotFoundException e) {
                                errReceiver.error(e);
                                return null;
                            }
                            return result;
                        }

                        @Override
                        public Result getWSDL(String suggestedFilename) {
                            File f = toFile(suggestedFilename);
                            wsdlFileName[0] = f;
                            return toResult(f);
                        }

                        public Result getSchemaOutput(String namespace, String suggestedFilename) {
                            if (namespace == null)
                                return null;
                            File f = toFile(suggestedFilename);
                            schemaFiles.put(namespace, f);
                            return toResult(f);
                        }

                        @Override
                        public Result getAbstractWSDL(Holder<String> filename) {
                            return toResult(toFile(filename.value));
                        }

                        @Override
                        public Result getSchemaOutput(String namespace, Holder<String> filename) {
                            return getSchemaOutput(namespace, filename.value);
                        }
                        // TODO pass correct impl's class name
                    });

            wsdlGenInfo.setContainer(container);
            wsdlGenInfo.setExtensions(ServiceFinder.find(WSDLGeneratorExtension.class).toArray());
            wsdlGenInfo.setInlineSchemas(options.inlineSchemas);
            rt.generateWSDL(wsdlGenInfo);


            if (options.wsgenReport != null)
                generateWsgenReport(endpointClass, (AbstractSEIModelImpl) rt.getModel(), wsdlFileName[0], schemaFiles);
        }
        return true;
    }

    private String property(String key) {
        try {
            String property = System.getProperty(key);
            return property != null ? property : "UNKNOWN";
        } catch (SecurityException ignored) {
            return "UNKNOWN";
        }
    }

    private List<File> getExternalFiles(List<String> exts) {
        List<File> files = new ArrayList<>();
        for (String ext : exts) {
            // first try absolute path ...
            File file = new File(ext);
            if (!file.exists()) {
                // then relative path ...
                file = new File(options.sourceDir.getAbsolutePath() + File.separator + ext);
            }
            files.add(file);
        }
        return files;
    }

    /**
     * Generates a small XML file that captures the key activity of wsgen,
     * so that test harness can pick up artifacts.
     */
    private void generateWsgenReport(Class<?> endpointClass, AbstractSEIModelImpl rtModel, File wsdlFile, Map<String, File> schemaFiles) {
        try {
            ReportOutput.Report report = TXW.create(ReportOutput.Report.class,
                    new StreamSerializer(new BufferedOutputStream(new FileOutputStream(options.wsgenReport))));

            report.wsdl(wsdlFile.getAbsolutePath());
            ReportOutput.writeQName(rtModel.getServiceQName(), report.service());
            ReportOutput.writeQName(rtModel.getPortName(), report.port());
            ReportOutput.writeQName(rtModel.getPortTypeName(), report.portType());

            report.implClass(endpointClass.getName());

            for (Map.Entry<String, File> e : schemaFiles.entrySet()) {
                ReportOutput.Schema s = report.schema();
                s.ns(e.getKey());
                s.location(e.getValue().getAbsolutePath());
            }

            report.commit();
        } catch (IOException e) {
            // this is code for the test, so we can be lousy in the error handling
            throw new Error(e);
        }
    }

    private float getVersion(String s) {
        return Float.parseFloat(s);
    }

    /**
     * "Namespace" for code needed to generate the report file.
     */
    static class ReportOutput {
        @XmlElement("report")
        interface Report extends TypedXmlWriter {
            @XmlElement
            void wsdl(String file); // location of WSDL

            @XmlElement
            QualifiedName portType();

            @XmlElement
            QualifiedName service();

            @XmlElement
            QualifiedName port();

            /**
             * Name of the class that has {@link javax.jws.WebService}.
             */
            @XmlElement
            void implClass(String name);

            @XmlElement
            Schema schema();
        }

        interface QualifiedName extends TypedXmlWriter {
            @XmlAttribute
            void uri(String ns);

            @XmlAttribute
            void localName(String localName);
        }

        interface Schema extends TypedXmlWriter {
            @XmlAttribute
            void ns(String ns);

            @XmlAttribute
            void location(String filePath);
        }

        private static void writeQName(QName n, QualifiedName w) {
            w.uri(n.getNamespaceURI());
            w.localName(n.getLocalPart());
        }
    }

    protected void usage(Options options) {
        // Just don't see any point in passing WsgenOptions
        // BadCommandLineException also shouldn't have options
        if (options == null)
            options = this.options;
        if (options instanceof WsgenOptions) {
            System.out.println(WscompileMessages.WSGEN_HELP("WSGEN",
                    ((WsgenOptions)options).protocols,
                    ((WsgenOptions)options).nonstdProtocols.keySet()));
            System.out.println(WscompileMessages.WSGEN_USAGE_EXTENSIONS());
            System.out.println(WscompileMessages.WSGEN_USAGE_EXAMPLES());
        }
    }

    class Listener extends WsimportListener {
        ConsoleErrorReporter cer = new ConsoleErrorReporter(out == null ? new PrintStream(new NullStream()) : out);

        @Override
        public void generatedFile(String fileName) {
            message(fileName);
        }

        @Override
        public void message(String msg) {
            out.println(msg);
        }

        @Override
        public void error(SAXParseException exception) {
            cer.error(exception);
        }

        @Override
        public void fatalError(SAXParseException exception) {
            cer.fatalError(exception);
        }

        @Override
        public void warning(SAXParseException exception) {
            cer.warning(exception);
        }

        @Override
        public void info(SAXParseException exception) {
            cer.info(exception);
        }
    }
}
