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

import org.apache.xmlbeans.*;
import org.apache.xmlbeans.impl.common.XmlErrorWatcher;
import org.apache.xmlbeans.impl.xb.xsdschema.SchemaDocument;
import org.apache.xmlbeans.impl.xb.xsdschema.SchemaDocument.Schema;

import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.net.URI;
import java.util.*;

public class SchemaTypeSystemCompiler {
    public static class Parameters {
        private SchemaTypeSystem existingSystem;
        private String name;
        private Schema[] schemas;
        private BindingConfig config;
        private SchemaTypeLoader linkTo;
        private XmlOptions options;
        private Collection<XmlError> errorListener;
        private boolean javaize;
        private URI baseURI;
        private Map<String, String> sourcesToCopyMap;
        private File schemasDir;

        public SchemaTypeSystem getExistingTypeSystem() {
            return existingSystem;
        }

        public void setExistingTypeSystem(SchemaTypeSystem system) {
            this.existingSystem = system;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public SchemaDocument.Schema[] getSchemas() {
            return schemas;
        }

        public void setSchemas(SchemaDocument.Schema[] schemas) {
            this.schemas = (schemas == null) ? null : schemas.clone();
        }

        public BindingConfig getConfig() {
            return config;
        }

        public void setConfig(BindingConfig config) {
            this.config = config;
        }

        public SchemaTypeLoader getLinkTo() {
            return linkTo;
        }

        public void setLinkTo(SchemaTypeLoader linkTo) {
            this.linkTo = linkTo;
        }

        public XmlOptions getOptions() {
            return options;
        }

        public void setOptions(XmlOptions options) {
            this.options = options;
        }

        public Collection<XmlError> getErrorListener() {
            return errorListener;
        }

        public void setErrorListener(Collection<XmlError> errorListener) {
            this.errorListener = errorListener;
        }

        public boolean isJavaize() {
            return javaize;
        }

        public void setJavaize(boolean javaize) {
            this.javaize = javaize;
        }

        public URI getBaseURI() {
            return baseURI;
        }

        public void setBaseURI(URI baseURI) {
            this.baseURI = baseURI;
        }

        public Map<String, String> getSourcesToCopyMap() {
            return sourcesToCopyMap;
        }

        public void setSourcesToCopyMap(Map<String, String> sourcesToCopyMap) {
            this.sourcesToCopyMap = sourcesToCopyMap;
        }

        public File getSchemasDir() {
            return schemasDir;
        }

        public void setSchemasDir(File schemasDir) {
            this.schemasDir = schemasDir;
        }

    }

    /**
     * Compiles a SchemaTypeSystem.  Use XmlBeans.compileXmlBeans() if you can.
     */
    public static SchemaTypeSystem compile(Parameters params) {
        return compileImpl(params.getExistingTypeSystem(), params.getName(),
            params.getSchemas(), params.getConfig(), params.getLinkTo(),
            params.getOptions(), params.getErrorListener(), params.isJavaize(),
            params.getBaseURI(), params.getSourcesToCopyMap(), params.getSchemasDir());
    }

    /**
     * Please do not invoke this method directly as the signature could change unexpectedly.
     * Use one of
     * {@link XmlBeans#loadXsd(XmlObject[])},
     * {@link XmlBeans#compileXsd(XmlObject[], SchemaTypeLoader, XmlOptions)},
     * or
     * {@link XmlBeans#compileXmlBeans(String, SchemaTypeSystem, XmlObject[], BindingConfig, SchemaTypeLoader, Filer, XmlOptions)}
     */
    public static SchemaTypeSystemImpl compile(String name, SchemaTypeSystem existingSTS,
                                               XmlObject[] input, BindingConfig config, SchemaTypeLoader linkTo, Filer filer, XmlOptions options)
        throws XmlException {
        options = XmlOptions.maskNull(options);
        ArrayList<Schema> schemas = new ArrayList<>();

        if (input != null) {
            for (int i = 0; i < input.length; i++) {
                if (input[i] instanceof Schema) {
                    schemas.add((Schema) input[i]);
                } else if (input[i] instanceof SchemaDocument && ((SchemaDocument) input[i]).getSchema() != null) {
                    schemas.add(((SchemaDocument) input[i]).getSchema());
                } else {
                    throw new XmlException("Thread " + Thread.currentThread().getName() + ": The " + i + "th supplied input is not a schema document: its type is " + input[i].schemaType());
                }
            }
        }

        Collection<XmlError> userErrors = options.getErrorListener();
        XmlErrorWatcher errorWatcher = new XmlErrorWatcher(userErrors);

        SchemaTypeSystemImpl stsi = compileImpl(existingSTS, name,
            schemas.toArray(new Schema[0]),
            config, linkTo, options, errorWatcher, filer != null, options.getBaseURI(),
            null, null);

        // if there is an error and compile didn't recover (stsi==null), throw exception
        if (errorWatcher.hasError() && stsi == null) {
            throw new XmlException(errorWatcher.firstError());
        }

        if (stsi != null && !stsi.isIncomplete() && filer != null) {
            stsi.save(filer);
            generateTypes(stsi, filer, options);
        }

        return stsi;
    }

    //
    // Compiles a SchemaTypeSystem
    //
    /* package */
    static SchemaTypeSystemImpl compileImpl(SchemaTypeSystem system, String name,
                                            Schema[] schemas, BindingConfig config, SchemaTypeLoader linkTo,
                                            XmlOptions options, Collection<XmlError> outsideErrors, boolean javaize,
                                            URI baseURI, Map<String, String> sourcesToCopyMap, File schemasDir) {
        if (linkTo == null) {
            throw new IllegalArgumentException("Must supply linkTo");
        }

        XmlErrorWatcher errorWatcher = new XmlErrorWatcher(outsideErrors);
        boolean incremental = system != null;

        // construct the state
        StscState state = StscState.start();
        boolean validate = (options == null || !options.isCompileNoValidation());
        try {
            state.setErrorListener(errorWatcher);
            state.setBindingConfig(config);
            state.setOptions(options);
            state.setGivenTypeSystemName(name);
            state.setSchemasDir(schemasDir);
            if (baseURI != null) {
                state.setBaseUri(baseURI);
            }

            // construct the classpath (you always get the builtin types)
            linkTo = SchemaTypeLoaderImpl.build(new SchemaTypeLoader[]{BuiltinSchemaTypeSystem.get(), linkTo}, null, null);
            state.setImportingTypeLoader(linkTo);

            List<Schema> validSchemas = new ArrayList<>(schemas.length);

            // load all the xsd files into it
            if (validate) {
                XmlOptions validateOptions = new XmlOptions().setErrorListener(errorWatcher);
                if (options != null && options.isValidateTreatLaxAsSkip()) {
                    validateOptions.setValidateTreatLaxAsSkip();
                }
                for (Schema schema : schemas) {
                    if (schema.validate(validateOptions)) {
                        validSchemas.add(schema);
                    }
                }
            } else {
                validSchemas.addAll(Arrays.asList(schemas));
            }

            Schema[] startWith = validSchemas.toArray(new Schema[0]);

            if (incremental) {
                Set<String> namespaces = new HashSet<>();
                startWith = getSchemasToRecompile((SchemaTypeSystemImpl) system, startWith, namespaces);
                state.initFromTypeSystem((SchemaTypeSystemImpl) system, namespaces);
            } else {
                state.setDependencies(new SchemaDependencies());
            }

            // deal with imports and includes
            StscImporter.SchemaToProcess[] schemasAndChameleons = StscImporter.resolveImportsAndIncludes(startWith, incremental);

            // call the translator so that it may also perform magic
            StscTranslator.addAllDefinitions(schemasAndChameleons);

            // call the resolver to do its magic
            StscResolver.resolveAll();

            // call the checker to check both restrictions and defaults
            StscChecker.checkAll();

            // call the javaizer to do its magic
            StscJavaizer.javaizeAllTypes(javaize);

            // construct the loader out of the state
            StscState.get().sts().loadFromStscState(state);

            // fill in the source-copy map
            if (sourcesToCopyMap != null) {
                sourcesToCopyMap.putAll(state.sourceCopyMap());
            }

            if (errorWatcher.hasError()) {
                // EXPERIMENTAL: recovery from compilation errors and partial type system
                if (state.allowPartial() && state.getRecovered() == errorWatcher.size()) {
                    // if partial type system allowed and all errors were recovered
                    StscState.get().sts().setIncomplete(true);
                } else {
                    // if any non-recoverable errors, return null
                    return null;
                }
            }

            if (system != null) {
                ((SchemaTypeSystemImpl) system).setIncomplete(true);
            }

            return StscState.get().sts();
        } finally {
            StscState.end();
        }
    }

    /**
     * Get the list of Schemas to be recompiled, based on the list of Schemas that
     * were modified.
     * We make use of the depencency information that we stored in the typesystem
     * and of the entity resolvers that have been set up
     */
    private static Schema[] getSchemasToRecompile(SchemaTypeSystemImpl system,
                                                  Schema[] modified, Set<String> namespaces) {
        Set<String> modifiedFiles = new HashSet<>();
        Map<String, SchemaDocument.Schema> haveFile = new HashMap<>();
        List<SchemaDocument.Schema> result = new ArrayList<>();
        for (Schema schema : modified) {
            String fileURL = schema.documentProperties().getSourceName();
            if (fileURL == null) {
                throw new IllegalArgumentException("One of the Schema files passed in" +
                                                   " doesn't have the source set, which prevents it to be incrementally" +
                                                   " compiled");
            }
            modifiedFiles.add(fileURL);
            haveFile.put(fileURL, schema);
            result.add(schema);
        }
        SchemaDependencies dep = system.getDependencies();
        List<String> nss = dep.getNamespacesTouched(modifiedFiles);
        namespaces.addAll(dep.computeTransitiveClosure(nss));
        List<String> needRecompilation = dep.getFilesTouched(namespaces);
        StscState.get().setDependencies(new SchemaDependencies(dep, namespaces));
        for (String url : needRecompilation) {
            Schema have = haveFile.get(url);
            if (have == null) {
                // We have to load the file from the entity resolver
                try {
                    XmlObject xdoc = StscImporter.DownloadTable.
                        downloadDocument(StscState.get().getS4SLoader(), null, url);
                    XmlOptions voptions = new XmlOptions();
                    voptions.setErrorListener(StscState.get().getErrorListener());
                    if (!(xdoc instanceof SchemaDocument) || !xdoc.validate(voptions)) {
                        StscState.get().error("Referenced document is not a valid schema, URL = " + url, XmlErrorCodes.CANNOT_FIND_RESOURCE, null);
                        continue;
                    }

                    SchemaDocument sDoc = (SchemaDocument) xdoc;

                    result.add(sDoc.getSchema());
                } catch (java.net.MalformedURLException mfe) {
                    StscState.get().error(XmlErrorCodes.EXCEPTION_LOADING_URL, new Object[]{"MalformedURLException", url, mfe.getMessage()}, null);
                } catch (IOException ioe) {
                    StscState.get().error(XmlErrorCodes.EXCEPTION_LOADING_URL, new Object[]{"IOException", url, ioe.getMessage()}, null);
                } catch (XmlException xmle) {
                    StscState.get().error(XmlErrorCodes.EXCEPTION_LOADING_URL, new Object[]{"XmlException", url, xmle.getMessage()}, null);
                }
            }
        }
        return result.toArray(new Schema[0]);
    }


    /**
     * Generate java source files for a SchemaTypeSystem.
     * Please do not invoke this method directly as the signature could change unexpectedly.
     * Use {@link org.apache.xmlbeans.XmlBeans#compileXmlBeans}
     *
     * @param system  the SchemaTypeSystem to generated java source for
     * @param filer   to create the java source files
     * @param options See {@link XmlOptions#setSchemaCodePrinter(org.apache.xmlbeans.SchemaCodePrinter)}
     * @return true if saving the generated source succeeded.
     */
    public static boolean generateTypes(SchemaTypeSystem system, Filer filer, XmlOptions options) {
        // partial type systems not allowed to be saved
        if (system instanceof SchemaTypeSystemImpl && ((SchemaTypeSystemImpl) system).isIncomplete()) {
            return false;
        }

        boolean success = true;

        List<SchemaType> types = new ArrayList<>();
        types.addAll(Arrays.asList(system.globalTypes()));
        types.addAll(Arrays.asList(system.documentTypes()));
        types.addAll(Arrays.asList(system.attributeTypes()));

        for (SchemaType type : types) {
            if (type.isBuiltinType()) {
                continue;
            }
            if (type.getFullJavaName() == null) {
                continue;
            }

            String fjn = type.getFullJavaName();

            try (Writer writer = filer.createSourceFile(fjn)) {
                // Generate interface class
                SchemaTypeCodePrinter.printType(writer, type, options);
            } catch (IOException e) {
                System.err.println("IO Error " + e);
                success = false;
            }

            fjn = type.getFullJavaImplName();

            try (Writer writer = filer.createSourceFile(fjn)) {
                // Generate Implementation class
                SchemaTypeCodePrinter.printTypeImpl(writer, type, options);
            } catch (IOException e) {
                System.err.println("IO Error " + e);
                success = false;
            }
        }

        return success;
    }
}
