/*   Copyright 2004 The Apache Software Foundation
 *
 *   Licensed 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.xmlbeans.impl.tool;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.FileScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Jar;
import org.apache.tools.ant.taskdefs.Javac;
import org.apache.tools.ant.taskdefs.MatchingTask;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;
import org.apache.xmlbeans.XmlError;
import org.apache.xmlbeans.impl.common.IOUtil;

import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URI;
import java.util.*;

/**
 * Modeled after Ant's javac and zip tasks.
 * <p>
 * Schema files to process, or directories of schema files, are set with the 'schema'
 * attribute, and can be filtered with 'includes' and 'excludes'.
 * Alternatively, one or more nested &lt;fileset&gt; elements can specify the
 * files and directories to be used to generate this XMLBean.
 * The include set can also define .java files that should be built as well.
 * See the FileSet documentation at http://jakarta.apache.org/ant/manual/index.html
 * for instructions on FileSets if you are unfamiliar with their usage.
 */

public class XMLBean extends MatchingTask {
    private final List<FileSet> schemas = new ArrayList<>();

    private Set<String> mdefnamespaces;

    private Path classpath;

    private File destfile,
        schema,
        srcgendir,
        classgendir;

    private boolean quiet,
        verbose,
        debug,
        optimize,
        download,
        srconly,
        noupa,
        nopvr,
        noann,
        novdoc,
        noext = false,
        failonerror = true,
        fork = true,
        includeAntRuntime = true,
        noSrcRegen,
        includeJavaRuntime = false,
        nowarn = false;

    private String typesystemname,
        forkedExecutable,
        compiler,
        debugLevel,
        memoryInitialSize,
        memoryMaximumSize,
        catalog,
        repackage;

    private final List<Extension> extensions = new ArrayList<>();

    private final Map<String, Set<File>> _extRouter = new HashMap<>(5);

    private static final String XSD = ".xsd",
        WSDL = ".wsdl",
        JAVA = ".java",
        XSDCONFIG = ".xsdconfig";


    public void execute() throws BuildException {
        /* VALIDATION */
        //required
        if (schemas.size() == 0
            && schema == null
            && fileset.getDir(project) == null) {
            String msg = "The 'schema' or 'dir' attribute or a nested fileset is required.";
            if (failonerror) {
                throw new BuildException(msg);
            } else {
                log(msg, Project.MSG_ERR);
                return;
            }
        }

        _extRouter.put(XSD, new HashSet<>());
        _extRouter.put(WSDL, new HashSet<>());
        _extRouter.put(JAVA, new HashSet<>());
        _extRouter.put(XSDCONFIG, new HashSet<>());

        File theBasedir = schema;

        if (schema != null) {
            if (schema.isDirectory()) {
                FileScanner scanner = getDirectoryScanner(schema);
                String[] paths = scanner.getIncludedFiles();
                processPaths(paths, scanner.getBasedir());
            } else {
                theBasedir = schema.getParentFile();
                processPaths(new String[]{schema.getName()}, theBasedir);
            }
        }

        if (fileset.getDir(project) != null) {
            schemas.add(fileset);
        }

        for (FileSet fs : schemas) {
            FileScanner scanner = fs.getDirectoryScanner(project);
            File basedir = scanner.getBasedir();
            String[] paths = scanner.getIncludedFiles();

            processPaths(paths, basedir);
        }

        Set<File> xsdList = _extRouter.get(XSD);
        Set<File> wsdlList = _extRouter.get(WSDL);

        if (xsdList.size() + wsdlList.size() == 0) {
            log("Could not find any xsd or wsdl files to process.", Project.MSG_WARN);
            return;
        }

        //optional
        Set<File> javaList = _extRouter.get(JAVA);
        Set<File> xsdconfigList = _extRouter.get(XSDCONFIG);

        if (srcgendir == null && srconly) {
            srcgendir = classgendir;
        }

        if (destfile == null && classgendir == null && !srconly) {
            destfile = new File("xmltypes.jar");
        }

        if (verbose) {
            quiet = false;
        }

        /* EXECUTION */

        File[] xsdArray = xsdList.toArray(new File[0]);
        File[] wsdlArray = wsdlList.toArray(new File[0]);
        File[] javaArray = javaList.toArray(new File[0]);
        File[] xsdconfigArray = xsdconfigList.toArray(new File[0]);
        ErrorLogger err = new ErrorLogger(verbose);

        boolean success = false;

        try {
            // create a temp directory
            File tmpdir = null;
            if (srcgendir == null || classgendir == null) {
                tmpdir = SchemaCodeGenerator.createTempDir();
            }
            if (srcgendir == null) {
                srcgendir = IOUtil.createDir(tmpdir, "src");
            }
            if (classgendir == null) {
                classgendir = IOUtil.createDir(tmpdir, "classes");
            }

            // use the system classpath if user didn't provide any
            if (classpath == null) {
                classpath = new Path(project);
                classpath.concatSystemClasspath();
            }

            // prepend the output directory on the classpath
            Path.PathElement pathElement = classpath.createPathElement();
            pathElement.setLocation(classgendir);

            String[] paths = classpath.list();
            File[] cp = new File[paths.length];
            for (int i = 0; i < paths.length; i++) {
                cp[i] = new File(paths[i]);
            }

            // generate the source
            SchemaCompiler.Parameters params = new SchemaCompiler.Parameters();
            params.setBaseDir(theBasedir);
            params.setXsdFiles(xsdArray);
            params.setWsdlFiles(wsdlArray);
            params.setJavaFiles(javaArray);
            params.setConfigFiles(xsdconfigArray);
            params.setClasspath(cp);
            params.setName(typesystemname);
            params.setSrcDir(srcgendir);
            params.setClassesDir(classgendir);
            params.setNojavac(true); // always compile using javac task below
            params.setDebug(debug);
            params.setVerbose(verbose);
            params.setQuiet(quiet);
            params.setDownload(download);
            params.setExtensions(extensions);
            params.setErrorListener(err);
            params.setCatalogFile(catalog);
            params.setIncrementalSrcGen(noSrcRegen);
            params.setMdefNamespaces(mdefnamespaces);
            params.setNoUpa(noupa);
            params.setNoPvr(nopvr);
            params.setNoAnn(noann);
            params.setNoVDoc(novdoc);
            params.setNoExt(noext);
            params.setRepackage(repackage);
            success = SchemaCompiler.compile(params);

            if (success && !srconly) {
                long start = System.currentTimeMillis();

                // compile the source
                Javac javac = new Javac();
                javac.setProject(project);
                javac.setTaskName(getTaskName());
                javac.setClasspath(classpath);
                if (compiler != null) {
                    javac.setCompiler(compiler);
                }
                javac.setDebug(debug);
                if (debugLevel != null) {
                    javac.setDebugLevel(debugLevel);
                }
                javac.setDestdir(classgendir);
                javac.setExecutable(forkedExecutable);
                javac.setFailonerror(failonerror);
                javac.setFork(fork);
                javac.setSource("1.8");
                javac.setTarget("1.8");
                javac.setIncludeantruntime(includeAntRuntime);
                javac.setIncludejavaruntime(includeJavaRuntime);
                javac.setNowarn(nowarn);
                javac.setSrcdir(new Path(project, srcgendir.getAbsolutePath()));
                if (memoryInitialSize != null) {
                    javac.setMemoryInitialSize(memoryInitialSize);
                }
                if (memoryMaximumSize != null) {
                    javac.setMemoryMaximumSize(memoryMaximumSize);
                }
                javac.setOptimize(optimize);
                javac.setVerbose(verbose);
                javac.execute();

                long finish = System.currentTimeMillis();
                if (!quiet) {
                    log("Time to compile code: " + ((double) (finish - start) / 1000.0) + " seconds");
                }

                if (destfile != null) {
                    // jar the compiled classes
                    Jar jar = new Jar();
                    jar.setProject(project);
                    jar.setTaskName(getTaskName());
                    jar.setBasedir(classgendir);
                    jar.setDestFile(destfile);
                    jar.execute();
                }
            }

            if (tmpdir != null) {
                SchemaCodeGenerator.tryHardToDelete(tmpdir);
            }
        } catch (BuildException e) {
            // re-throw anything thrown from javac or jar task
            throw e;
        } catch (Throwable e) {
            //interrupted means cancel
            if (e instanceof InterruptedException || failonerror) {
                throw new BuildException(e);
            }

            log("Exception while building schemas: " + e.getMessage(), Project.MSG_ERR);
            StringWriter sw = new StringWriter();
            e.printStackTrace(new PrintWriter(sw));
            log(sw.toString(), Project.MSG_VERBOSE);
        }

        if (!success && failonerror) {
            throw new BuildException(); //stop the build
        }
    }

    private void processPaths(String[] paths, File baseDir) {
        for (String s : paths) {
            int dot = s.lastIndexOf('.');
            if (dot > -1) {
                String possExt = s.substring(dot).toLowerCase();
                Set<File> set = _extRouter.get(possExt);

                if (set != null) {
                    set.add(new File(baseDir, s));
                }
            }
        }
    }

    public void addFileset(FileSet fileset) {
        schemas.add(fileset);
    }

    /////////////////////////////
    //Getter/Setters
    public File getSchema() {
        return schema;
    }

    /**
     * A file that points to either an individual schema file or a directory of files.
     * It is optional only if one or more &lt;fileset&gt; elements are nested in this
     * task.
     *
     * @param schema Required, unless a fileset element is nested.
     */
    public void setSchema(File schema) {
        this.schema = schema;
    }

    /**
     * The classpath to use if schemas in the fileset import definitions that are
     * supplied by other compiled xml beans JAR files, or if .java files are in the
     * schema fileset.
     *
     * @param classpath Optional.
     */
    public void setClasspath(Path classpath) {
        if (this.classpath != null) {
            this.classpath.append(classpath);
        } else {
            this.classpath = classpath;
        }
    }

    /**
     * Adds a path to the classpath.
     */
    public Path createClasspath() {
        if (classpath == null) {
            classpath = new Path(project);
        }
        return classpath.createPath();
    }

    /**
     * Adds a reference to a classpath defined elsewhere.
     *
     * @param classpathref Optional.
     */
    public void setClasspathRef(Reference classpathref) {
        if (classpath == null) {
            classpath = new Path(project);
        }

        classpath.createPath().setRefid(classpathref);
    }

    public Path getClasspath() {
        return classpath;
    }

    public File getDestfile() {
        return destfile;
    }

    /**
     * Define the name of the jar file created.  For instance, "myXMLBean.jar"
     * will output the results of this task into a jar with the same name.
     * Optional, defaults to "xmltypes.jar".
     *
     * @param destfile Optional.
     */
    public void setDestfile(File destfile) {
        this.destfile = destfile;
    }

    public File getSrcgendir() {
        return srcgendir;
    }

    /**
     * Set a location to generate .java files into.  Optional, defaults to
     * a temp dir.
     *
     * @param srcgendir Optional.
     */
    public void setSrcgendir(File srcgendir) {
        this.srcgendir = srcgendir;
    }

    public File getClassgendir() {
        return classgendir;
    }

    /**
     * Set a location to generate .class files into.  Optional, defaults to
     * a temp dir.
     *
     * @param classgendir Optional.
     */
    public void setClassgendir(File classgendir) {
        this.classgendir = classgendir;
    }

    /**
     * Choose the implementation for this particular task.
     *
     * @since Ant 1.5
     */
    public void setCompiler(String compiler) {
        this.compiler = compiler;
    }

    public boolean isDownload() {
        return download;
    }

    /**
     * Set to true to permit the compiler to download URLs for imports
     * and includes.  Defaults to false, meaning all imports and includes
     * must be copied locally.
     *
     * @param download Optional.
     */
    public void setDownload(boolean download) {
        this.download = download;
    }

    /**
     * If true, compiles with optimization enabled.
     */
    public void setOptimize(boolean optimize) {
        this.optimize = optimize;
    }

    /**
     * Gets the optimize flag.
     */
    public boolean getOptimize() {
        return optimize;
    }

    public boolean isVerbose() {
        return verbose;
    }

    /**
     * Controls the amount of output.  Defaults to true.
     *
     * @param verbose Optional.
     */
    public void setVerbose(boolean verbose) {
        this.verbose = verbose;
    }

    public boolean isQuiet() {
        return quiet;
    }

    /**
     * Controls the amount of output.  Defaults to false.
     *
     * @param quiet Optional.
     */
    public void setQuiet(boolean quiet) {
        this.quiet = quiet;
    }

    public boolean isDebug() {
        return debug;
    }

    /**
     * Get the value of debugLevel.
     *
     * @return value of debugLevel.
     */
    public String getDebugLevel() {
        return debugLevel;
    }

    /**
     * Keyword list to be appended to the -g command-line switch.
     * <p>
     * This will be ignored by all implementations except modern
     * and classic(ver >= 1.2). Legal values are none or a
     * comma-separated list of the following keywords: lines, vars,
     * and source. If debuglevel is not specified, by default, :none
     * will be appended to -g. If debug is not turned on, this attribute
     * will be ignored.
     *
     * @param v Value to assign to debugLevel.
     */
    public void setDebugLevel(String v) {
        this.debugLevel = v;
    }

    /**
     * Generate debugging symbols.
     *
     * @param debug Optional.
     */
    public void setDebug(boolean debug) {
        this.debug = debug;
    }

    /**
     * If true, forks the javac compiler.
     *
     * @param f "true|false|on|off|yes|no"
     */
    public void setFork(boolean f) {
        fork = f;
    }

    /**
     * Sets the the name of the javac executable.
     *
     * <p>Ignored unless fork is true or extJavac has been specified
     * as the compiler.</p>
     */
    public void setExecutable(String forkExec) {
        forkedExecutable = forkExec;
    }

    public String getExecutable() {
        return forkedExecutable;
    }

    public boolean isSrconly() {
        return srconly;
    }

    /**
     * A value of true means that only source will be generated.  Optional,
     * default is false.
     *
     * @param srconly Optional.
     */
    public void setSrconly(boolean srconly) {
        this.srconly = srconly;
    }

    public String getTypesystemname() {
        return typesystemname;
    }

    /**
     * One or more SchemaCompiler extensions can be passed in via the &lt;extension> subelement.
     * Schema Compiler extensions must implement the interface com.xbean.too.SchemaCompilerExtension
     */
    public Extension createExtension() {
        Extension e = new Extension();
        extensions.add(e);
        return e;
    }

    /**
     * One or more namespaces in which duplicate definitions are to be ignored
     * can be passed in via the &lt;ignoreDuplicatesInNamespaces> subelement.
     */
    public void setIgnoreDuplicatesInNamespaces(String namespaces) {
        mdefnamespaces = new HashSet<>();
        StringTokenizer st = new StringTokenizer(namespaces, ",");
        while (st.hasMoreTokens()) {
            String namespace = st.nextToken().trim();
            mdefnamespaces.add(namespace);
        }
    }

    public String getIgnoreDuplicatesInNamespaces() {
        return mdefnamespaces == null ? null : String.join(",", mdefnamespaces);

    }

    /**
     * The name of the package that the TypeSystemHolder class should be
     * generated in. Normally this should be left unspecified.  None of
     * the xml beans are generated in this package.
     * <BR><BR>Use .xsdconfig files to modify xml bean package or class names.
     *
     * @param typesystemname Optional.
     */
    public void setTypesystemname(String typesystemname) {
        this.typesystemname = typesystemname;
    }

    public boolean isFailonerror() {
        return failonerror;
    }

    /**
     * Determines whether or not the ant target will continue if the XMLBean
     * creation encounters a build error.  Defaults to true.  Optional.
     *
     * @param failonerror Optional.
     */
    public void setFailonerror(boolean failonerror) {
        this.failonerror = failonerror;
    }

    public boolean isIncludeAntRuntime() {
        return includeAntRuntime;
    }

    public void setIncludeAntRuntime(boolean includeAntRuntime) {
        this.includeAntRuntime = includeAntRuntime;
    }

    public boolean isIncludeJavaRuntime() {
        return includeJavaRuntime;
    }

    public void setIncludeJavaRuntime(boolean includeJavaRuntime) {
        this.includeJavaRuntime = includeJavaRuntime;
    }

    public boolean isNowarn() {
        return nowarn;
    }

    public void setNowarn(boolean nowarn) {
        this.nowarn = nowarn;
    }

    public boolean isNoSrcRegen() {
        return noSrcRegen;
    }

    public void setNoSrcRegen(boolean noSrcRegen) {
        this.noSrcRegen = noSrcRegen;
    }

    /**
     * Set the initial memory size of the underlying javac process.
     */
    public String getMemoryInitialSize() {
        return memoryInitialSize;
    }

    public void setMemoryInitialSize(String memoryInitialSize) {
        this.memoryInitialSize = memoryInitialSize;
    }

    /**
     * Set the maximum memory size of the underlying javac process.
     */
    public String getMemoryMaximumSize() {
        return memoryMaximumSize;
    }

    public void setMemoryMaximumSize(String memoryMaximumSize) {
        this.memoryMaximumSize = memoryMaximumSize;
    }

    /**
     * Do not enforce the unique particle attribution rule.
     */
    public void setNoUpa(boolean noupa) {
        this.noupa = noupa;
    }

    public boolean isNoUpa() {
        return noupa;
    }

    /**
     * Do not enforce the particle valid (restriction) rule.
     */
    public void setNoPvr(boolean nopvr) {
        this.nopvr = nopvr;
    }

    public boolean isNoPvr() {
        return nopvr;
    }

    /**
     * Skip over schema &lt;annotation%gt; elements.
     */
    public void setNoAnnotations(boolean noann) {
        this.noann = noann;
    }

    public boolean isNoAnnotations() {
        return noann;
    }

    /**
     * Do not validate the contents of schema &lt;documentation&gt; elements.
     */
    public void setNoValidateDoc(boolean novdoc) {
        this.novdoc = novdoc;
    }

    public boolean isNoValidateDoc() {
        return novdoc;
    }

    /**
     * Ignore extensions found in .xsdconfig files
     *
     * @param noext Ignore extensions
     */
    public void setNoExt(boolean noext) {
        this.noext = noext;
    }

    public boolean isNoExt() {
        return noext;
    }

    //REVIEW this allows people to deal with the case where they drag in
    //more files for compilation than they should.  not sure if this is
    //a good thing or not
    private String source = null;

    public void setSource(String s) {
        source = s;
    }

    /**
     * Gets the XML Catalog file for org.apache.xml.resolver.tools.CatalogResolver. (Note: needs resolver.jar from http://xml.apache.org/commons/components/resolver/index.html)
     */
    public String getCatalog() {
        return catalog;
    }

    /**
     * Sets the XML Catalog file for org.apache.xml.resolver.tools.CatalogResolver. (Note: needs resolver.jar from http://xml.apache.org/commons/components/resolver/index.html)
     */
    public void setCatalog(String catalog) {
        this.catalog = catalog;
    }

    public String getRepackage() {
        return repackage;
    }

    public void setRepackage(String repackage) {
        this.repackage = repackage;
    }

    private static URI uriFromFile(File f) {
        if (f == null) {
            return null;
        }

        try {
            return f.getCanonicalFile().toURI();
        } catch (java.io.IOException e) {
            // Don't spit out an exception here because on Windows you'll get one
            // if the filename is "aux", "lpt1", etc. It's the caller's responsibility
            // to deal with those cases correctly, usually by calling FileSvc.invalidPathCheck()
            // MessageSvc.get().logException(e);
            return f.getAbsoluteFile().toURI();
        }
    }

    public class ErrorLogger extends AbstractCollection<XmlError> {
        private final boolean _noisy;
        private final URI _baseURI;

        public ErrorLogger(boolean noisy) {
            _noisy = noisy;
            _baseURI = uriFromFile(project.getBaseDir());
        }

        public boolean add(XmlError err) {
            if (err.getSeverity() == XmlError.SEVERITY_ERROR) {
                log(err.toString(_baseURI), Project.MSG_ERR);
            } else if (err.getSeverity() == XmlError.SEVERITY_WARNING) {
                log(err.toString(_baseURI), Project.MSG_WARN);
            } else if (_noisy) {
                log(err.toString(_baseURI), Project.MSG_INFO);
            }
            return false;
        }

        public Iterator<XmlError> iterator() {
            return Collections.emptyIterator();
        }

        public int size() {
            return 0;
        }
    }
}
