/*   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.xmlbeans.XmlBeans;
import org.apache.xmlbeans.XmlOptions;
import org.apache.xmlbeans.impl.common.IOUtil;
import org.apache.xmlbeans.impl.util.HexBin;
import org.apache.xmlbeans.impl.xb.xsdownload.DownloadedSchemaEntry;
import org.apache.xmlbeans.impl.xb.xsdownload.DownloadedSchemasDocument;
import org.apache.xmlbeans.impl.xb.xsdownload.DownloadedSchemasDocument.DownloadedSchemas;
import org.apache.xmlbeans.impl.xb.xsdschema.SchemaDocument;
import org.apache.xmlbeans.impl.xb.xsdschema.SchemaDocument.Schema;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public abstract class BaseSchemaResourceManager extends SchemaImportResolver {
    private static final String USER_AGENT = "XMLBeans/" + XmlBeans.getVersion() + " (" + XmlBeans.getTitle() + ")";

    private String _defaultCopyDirectory;
    private DownloadedSchemasDocument _importsDoc;
    private final Map<String, SchemaResource> _resourceForFilename = new HashMap<>();
    private final Map<String, SchemaResource> _resourceForURL = new HashMap<>();
    private final Map<String, SchemaResource> _resourceForNamespace = new HashMap<>();
    private final Map<String, SchemaResource> _resourceForDigest = new HashMap<>();
    private final Map<DownloadedSchemaEntry, SchemaResource> _resourceForCacheEntry = new HashMap<>();
    private Set<SchemaResource> _redownloadSet = new HashSet<>();

    protected BaseSchemaResourceManager() {
        // concrete subclasses should call init in their constructors
    }

    protected final void init() {
        if (fileExists(getIndexFilename())) {
            try {
                _importsDoc = DownloadedSchemasDocument.Factory.parse(inputStreamForFile(getIndexFilename()));
            } catch (IOException e) {
                _importsDoc = null;
            } catch (Exception e) {
                throw new IllegalStateException("Problem reading xsdownload.xml: please fix or delete this file", e);
            }
        }
        if (_importsDoc == null) {
            try {
                _importsDoc = DownloadedSchemasDocument.Factory.parse(
                    "<dls:downloaded-schemas xmlns:dls='http://www.bea.com/2003/01/xmlbean/xsdownload' defaultDirectory='" + getDefaultSchemaDir() + "'/>"
                );
            } catch (Exception e) {
                throw new IllegalStateException(e);
            }
        }

        String defaultDir = _importsDoc.getDownloadedSchemas().getDefaultDirectory();
        if (defaultDir == null) {
            defaultDir = getDefaultSchemaDir();
        }
        _defaultCopyDirectory = defaultDir;

        // now initialize data structures
        DownloadedSchemaEntry[] entries = _importsDoc.getDownloadedSchemas().getEntryArray();
        for (DownloadedSchemaEntry entry : entries) {
            updateResource(entry);
        }
    }

    public final void writeCache() throws IOException {
        InputStream input = _importsDoc.newInputStream(new XmlOptions().setSavePrettyPrint());
        writeInputStreamToFile(input, getIndexFilename());
    }

    public final void processAll(boolean sync, boolean refresh, boolean imports) {
        _redownloadSet = refresh ? new HashSet<>() : null;

        String[] allFilenames = getAllXSDFilenames();

        if (sync) {
            syncCacheWithLocalXsdFiles(allFilenames, false);
        }

        SchemaResource[] starters = _resourceForFilename.values().toArray(new SchemaResource[0]);

        if (refresh) {
            redownloadEntries(starters);
        }

        if (imports) {
            resolveImports(starters);
        }

        _redownloadSet = null;
    }

    public final void process(String[] uris, String[] filenames, boolean sync, boolean refresh, boolean imports) {
        _redownloadSet = refresh ? new HashSet<>() : null;

        if (filenames.length > 0) {
            syncCacheWithLocalXsdFiles(filenames, true);
        } else if (sync) {
            syncCacheWithLocalXsdFiles(getAllXSDFilenames(), false);
        }

        Set<SchemaResource> starterset = new HashSet<>();

        for (String s : uris) {
            SchemaResource resource = (SchemaResource) lookupResource(null, s);
            if (resource != null) {
                starterset.add(resource);
            }
        }

        for (String filename : filenames) {
            SchemaResource resource = _resourceForFilename.get(filename);
            if (resource != null) {
                starterset.add(resource);
            }
        }

        SchemaResource[] starters = starterset.toArray(new SchemaResource[0]);

        if (refresh) {
            redownloadEntries(starters);
        }

        if (imports) {
            resolveImports(starters);
        }

        _redownloadSet = null;
    }

    /**
     * Adds items to the cache that point to new files that aren't
     * described in the cache, and optionally deletes old entries.
     * <p>
     * If an old file is gone and a new file is
     * found with exactly the same contents, the cache entry is moved
     * to point to the new file.
     */
    public final void syncCacheWithLocalXsdFiles(String[] filenames, boolean deleteOnlyMentioned) {
        Set<SchemaResource> seenResources = new HashSet<>();
        Set<SchemaResource> vanishedResources = new HashSet<>();

        for (String filename : filenames) {
            // first, if the filename matches exactly, trust the filename
            SchemaResource resource = _resourceForFilename.get(filename);
            if (resource != null) {
                if (fileExists(filename)) {
                    seenResources.add(resource);
                } else {
                    vanishedResources.add(resource);
                }
                continue;
            }

            // new file that is not in the index?
            // not if the digest is known to the index and the original file is gone - that's a rename!
            String digest = null;
            try {
                digest = shaDigestForFile(filename);
                resource = _resourceForDigest.get(digest);
                if (resource != null) {
                    String oldFilename = resource.getFilename();
                    if (!fileExists(oldFilename)) {
                        warning("File " + filename + " is a rename of " + oldFilename);
                        resource.setFilename(filename);
                        seenResources.add(resource);
                        if (_resourceForFilename.get(oldFilename) == resource) {
                            _resourceForFilename.remove(oldFilename);
                        }
                        if (_resourceForFilename.containsKey(filename)) {
                            _resourceForFilename.put(filename, resource);
                        }
                        continue;
                    }
                }
            } catch (IOException e) {
                // unable to read digest... no problem, ignore then
            }

            // ok, this really is a new XSD file then, of unknown URL origin
            DownloadedSchemaEntry newEntry = addNewEntry();
            newEntry.setFilename(filename);
            warning("Caching information on new local file " + filename);
            if (digest != null) {
                newEntry.setSha1(digest);
            }

            seenResources.add(updateResource(newEntry));
        }

        if (deleteOnlyMentioned) {
            deleteResourcesInSet(vanishedResources, true);
        } else {
            deleteResourcesInSet(seenResources, false);
        }
    }

    /**
     * Iterates through every entry and refetches it from its primary URL,
     * if known.  Replaces the contents of the file if the data is different.
     */
    private void redownloadEntries(SchemaResource[] resources) {
        for (SchemaResource resource : resources) {
            redownloadResource(resource);
        }
    }

    private void deleteResourcesInSet(Set<SchemaResource> seenResources, boolean setToDelete) {
        Set<DownloadedSchemaEntry> seenCacheEntries = new HashSet<>();
        for (SchemaResource resource : seenResources) {
            seenCacheEntries.add(resource._cacheEntry);
        }

        DownloadedSchemas downloadedSchemas = _importsDoc.getDownloadedSchemas();
        for (int i = 0; i < downloadedSchemas.sizeOfEntryArray(); i++) {
            DownloadedSchemaEntry cacheEntry = downloadedSchemas.getEntryArray(i);

            if (seenCacheEntries.contains(cacheEntry) == setToDelete) {
                SchemaResource resource = _resourceForCacheEntry.get(cacheEntry);

                if (resource != null) {
                    warning("Removing obsolete cache entry for " + resource.getFilename());
                    _resourceForCacheEntry.remove(cacheEntry);

                    if (resource == _resourceForFilename.get(resource.getFilename())) {
                        _resourceForFilename.remove(resource.getFilename());
                    }

                    if (resource == _resourceForDigest.get(resource.getSha1())) {
                        _resourceForDigest.remove(resource.getSha1());
                    }

                    if (resource == _resourceForNamespace.get(resource.getNamespace())) {
                        _resourceForNamespace.remove(resource.getNamespace());
                    }

                    // Finally, any or all URIs
                    String[] urls = resource.getSchemaLocationArray();
                    for (String url : urls) {
                        if (resource == _resourceForURL.get(url)) {
                            _resourceForURL.remove(url);
                        }
                    }
                }

                downloadedSchemas.removeEntry(i);
                i -= 1;
            }
        }
    }

    private SchemaResource updateResource(DownloadedSchemaEntry entry) {
        // The file
        String filename = entry.getFilename();
        if (filename == null) {
            return null;
        }

        SchemaResource resource = new SchemaResource(entry);
        _resourceForCacheEntry.put(entry, resource);

        if (!_resourceForFilename.containsKey(filename)) {
            _resourceForFilename.put(filename, resource);
        }

        // The digest
        String digest = resource.getSha1();
        if (digest != null) {
            if (!_resourceForDigest.containsKey(digest)) {
                _resourceForDigest.put(digest, resource);
            }
        }

        // Next, the namespace
        String namespace = resource.getNamespace();
        if (namespace != null) {
            if (!_resourceForNamespace.containsKey(namespace)) {
                _resourceForNamespace.put(namespace, resource);
            }
        }

        // Finally, any or all URIs
        String[] urls = resource.getSchemaLocationArray();
        for (String url : urls) {
            if (!_resourceForURL.containsKey(url)) {
                _resourceForURL.put(url, resource);
            }
        }

        return resource;
    }

    private static DigestInputStream digestInputStream(InputStream input) {
        MessageDigest sha;
        try {
            sha = MessageDigest.getInstance("SHA");
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException(e);
        }

        return new DigestInputStream(input, sha);
    }

    private DownloadedSchemaEntry addNewEntry() {
        return _importsDoc.getDownloadedSchemas().addNewEntry();
    }

    private class SchemaResource implements SchemaImportResolver.SchemaResource {
        SchemaResource(DownloadedSchemaEntry entry) {
            _cacheEntry = entry;
        }

        DownloadedSchemaEntry _cacheEntry;

        public void setFilename(String filename) {
            _cacheEntry.setFilename(filename);
        }

        public String getFilename() {
            return _cacheEntry.getFilename();
        }

        public Schema getSchema() {
            if (!fileExists(getFilename())) {
                redownloadResource(this);
            }

            try {
                return SchemaDocument.Factory.parse(inputStreamForFile(getFilename())).getSchema();
            } catch (Exception e) {
                return null; // return null if _any_ problems reading schema file
            }
        }

        public String getSha1() {
            return _cacheEntry.getSha1();
        }

        public String getNamespace() {
            return _cacheEntry.getNamespace();
        }

        public void setNamespace(String namespace) {
            _cacheEntry.setNamespace(namespace);
        }

        public String getSchemaLocation() {
            if (_cacheEntry.sizeOfSchemaLocationArray() > 0) {
                return _cacheEntry.getSchemaLocationArray(0);
            }
            return null;
        }

        public String[] getSchemaLocationArray() {
            return _cacheEntry.getSchemaLocationArray();
        }

        public int hashCode() {
            return getFilename().hashCode();
        }

        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }

            if (!(obj instanceof SchemaResource)) {
                return false;
            }

            SchemaResource sr = (SchemaResource) obj;
            return getFilename().equals(sr.getFilename());
        }

        public void addSchemaLocation(String schemaLocation) {
            _cacheEntry.addSchemaLocation(schemaLocation);
        }
    }

    /**
     * Called when the ImportLoader wishes to resolve the
     * given import.  Should return a SchemaResource whose
     * "equals" relationship reveals when a SchemaResource is
     * duplicated and shouldn't be examined again.
     * <p>
     * Returns null if the resource reference should be ignored.
     */
    public SchemaImportResolver.SchemaResource lookupResource(String nsURI, String schemaLocation) {
        SchemaResource result = fetchFromCache(nsURI, schemaLocation);
        if (result != null) {
            if (_redownloadSet != null) {
                redownloadResource(result);
            }
            return result;
        }

        if (schemaLocation == null) {
            warning("No cached schema for namespace '" + nsURI + "', and no url specified");
            return null;
        }

        result = copyOrIdentifyDuplicateURL(schemaLocation, nsURI);
        if (_redownloadSet != null) {
            _redownloadSet.add(result);
        }
        return result;
    }

    private SchemaResource fetchFromCache(String nsURI, String schemaLocation) {
        SchemaResource result;

        if (schemaLocation != null) {
            result = _resourceForURL.get(schemaLocation);
            if (result != null) {
                return result;
            }
        }

        if (nsURI != null) {
            result = _resourceForNamespace.get(nsURI);
            if (result != null) {
                return result;
            }
        }

        return null;
    }

    private String uniqueFilenameForURI(String schemaLocation) throws IOException, URISyntaxException {
        String localFilename = new URI(schemaLocation).getRawPath();
        int i = localFilename.lastIndexOf('/');
        if (i >= 0) {
            localFilename = localFilename.substring(i + 1);
        }
        if (localFilename.endsWith(".xsd")) {
            localFilename = localFilename.substring(0, localFilename.length() - 4);
        }
        if (localFilename.length() == 0) {
            localFilename = "schema";
        }

        // TODO: remove other unsafe characters for filenames?

        String candidateFilename = localFilename;
        int suffix = 1;
        while (suffix < 1000) {
            String candidate = _defaultCopyDirectory + "/" + candidateFilename + ".xsd";
            if (!fileExists(candidate)) {
                return candidate;
            }
            suffix += 1;
            candidateFilename = localFilename + suffix;
        }

        throw new IOException("Problem with filename " + localFilename + ".xsd");
    }

    private void redownloadResource(SchemaResource resource) {
        if (_redownloadSet != null) {
            if (_redownloadSet.contains(resource)) {
                return;
            }
            _redownloadSet.add(resource);
        }

        String filename = resource.getFilename();
        String schemaLocation = resource.getSchemaLocation();
        String digest;

        // nothing to do?
        if (schemaLocation == null || filename == null) {
            return;
        }

        ByteArrayOutputStream buffer = new ByteArrayOutputStream();

        try {
            URL url = new URL(schemaLocation);
            URLConnection conn = url.openConnection();
            conn.addRequestProperty("User-Agent", USER_AGENT);
            conn.addRequestProperty("Accept", "application/xml, text/xml, */*");
            DigestInputStream input = digestInputStream(conn.getInputStream());
            IOUtil.copyCompletely(input, buffer);
            digest = HexBin.bytesToString(input.getMessageDigest().digest());
        } catch (Exception e) {
            warning("Could not copy remote resource " + schemaLocation + ":" + e.getMessage());
            return;
        }

        if (digest.equals(resource.getSha1()) && fileExists(filename)) {
            warning("Resource " + filename + " is unchanged from " + schemaLocation + ".");
            return;
        }

        try {
            InputStream source = new ByteArrayInputStream(buffer.toByteArray());
            writeInputStreamToFile(source, filename);
        } catch (IOException e) {
            warning("Could not write to file " + filename + " for " + schemaLocation + ":" + e.getMessage());
            return;
        }

        warning("Refreshed " + filename + " from " + schemaLocation);
    }

    private SchemaResource copyOrIdentifyDuplicateURL(String schemaLocation, String namespace) {
        String targetFilename;
        String digest;
        SchemaResource result;

        try {
            targetFilename = uniqueFilenameForURI(schemaLocation);
        } catch (URISyntaxException e) {
            warning("Invalid URI '" + schemaLocation + "':" + e.getMessage());
            return null;
        } catch (IOException e) {
            warning("Could not create local file for " + schemaLocation + ":" + e.getMessage());
            return null;
        }

        try {
            URL url = new URL(schemaLocation);
            DigestInputStream input = digestInputStream(url.openStream());
            writeInputStreamToFile(input, targetFilename);
            digest = HexBin.bytesToString(input.getMessageDigest().digest());
        } catch (Exception e) {
            warning("Could not copy remote resource " + schemaLocation + ":" + e.getMessage());
            return null;
        }

        result = _resourceForDigest.get(digest);
        if (result != null) {
            deleteFile(targetFilename);
            result.addSchemaLocation(schemaLocation);
            if (!_resourceForURL.containsKey(schemaLocation)) {
                _resourceForURL.put(schemaLocation, result);
            }
            return result;
        }

        warning("Downloaded " + schemaLocation + " to " + targetFilename);

        DownloadedSchemaEntry newEntry = addNewEntry();
        newEntry.setFilename(targetFilename);
        newEntry.setSha1(digest);
        if (namespace != null) {
            newEntry.setNamespace(namespace);
        }
        newEntry.addSchemaLocation(schemaLocation);
        return updateResource(newEntry);
    }

    /**
     * Updates actual namespace in the table.
     */
    public void reportActualNamespace(SchemaImportResolver.SchemaResource rresource, String actualNamespace) {
        SchemaResource resource = (SchemaResource) rresource;
        String oldNamespace = resource.getNamespace();
        if (oldNamespace != null && _resourceForNamespace.get(oldNamespace) == resource) {
            _resourceForNamespace.remove(oldNamespace);
        }
        if (!_resourceForNamespace.containsKey(actualNamespace)) {
            _resourceForNamespace.put(actualNamespace, resource);
        }
        resource.setNamespace(actualNamespace);
    }

    private String shaDigestForFile(String filename) throws IOException {
        DigestInputStream str = digestInputStream(inputStreamForFile(filename));

        byte[] dummy = new byte[4096];
        int i = 1;
        while (i > 0) {
            i = str.read(dummy);
        }

        str.close();

        return HexBin.bytesToString(str.getMessageDigest().digest());
    }

    // SOME METHODS TO OVERRIDE ============================

    protected String getIndexFilename() {
        return "./xsdownload.xml";
    }

    protected String getDefaultSchemaDir() {
        return "./schema";
    }

    /**
     * Produces diagnostic messages such as "downloading X to file Y".
     */
    abstract protected void warning(String msg);

    /**
     * Returns true if the given filename exists.  The filenames
     * are of the form "/foo/bar/zee.xsd" and should be construed
     * as rooted at the root of the project.
     */
    abstract protected boolean fileExists(String filename);

    /**
     * Gets the data in the given filename as an InputStream.
     */
    abstract protected InputStream inputStreamForFile(String filename) throws IOException;

    /**
     * Writes an entire file in one step.  An InputStream is passed and
     * copied to the file.
     */
    abstract protected void writeInputStreamToFile(InputStream input, String filename) throws IOException;

    /**
     * Deletes a file.  Sometimes immediately after writing a new file
     * we notice that it's exactly the same as an existing file and
     * we delete it. We never delete a file that was given to us
     * by the user.
     */
    abstract protected void deleteFile(String filename);

    /**
     * Returns a list of all the XSD filesnames in the project.
     */
    abstract protected String[] getAllXSDFilenames();
}
