/*
 * 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.sling.feature.io.artifacts;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.ServiceLoader;

import org.apache.sling.feature.ArtifactId;
import org.apache.sling.feature.io.artifacts.spi.ArtifactProvider;
import org.apache.sling.feature.io.artifacts.spi.ArtifactProviderContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The artifact manager is the central service to get artifacts.
 * It uses {@link ArtifactProvider}s to get artifacts. The
 * providers are loaded using the service loader.
 */
public class ArtifactManager implements AutoCloseable {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /** The map of providers. */
    private final Map<String, ArtifactProvider> providers;

    /** The configuration */
    private final ArtifactManagerConfig config;

    /**
     * Get an artifact manager based on the configuration
     * @param config The configuration
     * @return The artifact manager
     * @throws IOException If the manager can't be initialized
     */
    public static ArtifactManager getArtifactManager(final ArtifactManagerConfig config) throws IOException {
        final ServiceLoader<ArtifactProvider> loader = ServiceLoader.load(ArtifactProvider.class);
        final Map<String, ArtifactProvider> providers = new HashMap<>();
        for(final ArtifactProvider provider : loader) {
            providers.put(provider.getProtocol(), provider);
        }

        final String[] repositoryURLs = new String[config.getRepositoryUrls().length];
        int index = 0;
        for(final String urlString : config.getRepositoryUrls()) {
            repositoryURLs[index] = urlString;
            index++;
        }
        // default
        if ( !providers.containsKey("*") ) {
            providers.put("*", new DefaultArtifactHandler());
        }

        return new ArtifactManager(config, providers);
    }

    ArtifactManager(final ArtifactManagerConfig config, final Map<String, ArtifactProvider> providers)
    throws IOException {
        this.config = config;
        this.providers = providers;
        try {
            for(final ArtifactProvider provider : this.providers.values()) {
                provider.init(config);
            }
        } catch ( final IOException io) {
            shutdown();
            throw io;
        }
    }

    /**
     * Shutdown the artifact manager.
     */
    public void shutdown() {
        for(final ArtifactProvider provider : this.providers.values()) {
            provider.shutdown();
        }
        this.providers.clear();
    }

    @Override
    public void close()
    {
        shutdown();
    }

    private final URL getArtifactFromProviders(final String url, final String relativeCachePath) throws IOException {
        final int pos = url.indexOf(":");
        final String scheme = url.substring(0, pos);

        ArtifactProvider provider = this.providers.get(scheme);
        if ( provider == null ) {
            provider = this.providers.get("*");
        }
        if ( provider == null ) {
            throw new IOException("No URL provider found for " + url);
        }
        return provider.getArtifact(url, relativeCachePath);
    }

    /**
     * Get the full artifact url and file for an artifact.
     * @param url Artifact url or relative path.
     * @return Absolute url and file in the form of a handler.
     * @throws IOException If something goes wrong.
     */
    public ArtifactHandler getArtifactHandler(final String url) throws IOException {
        logger.debug("Trying to get artifact for {}", url);

        final String path;

        if ( url.startsWith("mvn:") ) {
            // mvn url
            path = ArtifactId.fromMvnUrl(url).toMvnPath();

        } else if ( url.startsWith(":") ) {
            // repository path
            path = url.substring(1);

        } else if ( url.indexOf(":/") > 0 ) {

            // absolute URL
            int pos = url.indexOf(":/") + 2;
            while ( url.charAt(pos) == '/') {
                pos++;
            }
            final URL file = this.getArtifactFromProviders(url, url.substring(pos));
            if ( file == null ) {
                throw new IOException("Artifact " + url + " not found.");
            }
            return new ArtifactHandler(url, file);

        } else {
            // file (either relative or absolute)
            final File f = new File(url);
            if ( !f.exists()) {
                throw new IOException("Artifact " + url + " not found.");
            }
            return new ArtifactHandler(f.toURI().toString(), f.toURI().toURL());
        }
        logger.debug("Querying repositories for {}", path);

        for(final String repoUrl : this.config.getRepositoryUrls()) {
            final StringBuilder builder = new StringBuilder();
            builder.append(repoUrl);
            builder.append('/');
            builder.append(path);

            final String artifactUrl = builder.toString();
            final int pos = artifactUrl.indexOf(":");
            final String scheme = artifactUrl.substring(0, pos);

            ArtifactProvider handler = this.providers.get(scheme);
            if ( handler == null ) {
                handler = this.providers.get("*");
            }
            if ( handler == null ) {
                throw new IOException("No URL handler found for " + artifactUrl);
            }

            logger.debug("Checking {} to get artifact from {}", handler, artifactUrl);

            final URL file = handler.getArtifact(artifactUrl, path);
            if ( file != null ) {
                logger.debug("Found artifact {}", artifactUrl);
                return new ArtifactHandler(artifactUrl, file);
            }

            // check for SNAPSHOT
            final int lastSlash = artifactUrl.lastIndexOf('/');
            final int startSnapshot = artifactUrl.indexOf("-SNAPSHOT", lastSlash + 1);

            if ( startSnapshot > -1 ) {
                // special snapshot handling
                final String metadataUrl = artifactUrl.substring(0, lastSlash) + "/maven-metadata.xml";
                try {
                    final ArtifactHandler metadataHandler = this.getArtifactHandler(metadataUrl);

                    final String contents = getFileContents(metadataHandler);

                    final String latestVersion = getLatestSnapshot(contents);
                    if ( latestVersion != null ) {
                        final String name = artifactUrl.substring(lastSlash); // includes slash
                        final String fullURL = artifactUrl.substring(0, lastSlash) + name.replace("SNAPSHOT", latestVersion);
                        int pos2 = fullURL.indexOf(":/") + 2;
                        while ( fullURL.charAt(pos2) == '/') {
                            pos2++;
                        }
                        final URL file2 = this.getArtifactFromProviders(fullURL, path);
                        if ( file2 == null ) {
                            throw new IOException("Artifact " + fullURL + " not found.");
                        }
                        return new ArtifactHandler(artifactUrl, file2);
                    }
                } catch ( final IOException ignore ) {
                    // we ignore this but report the original 404
                }
            }
        }

        throw new IOException("Artifact " + url + " not found in any repository.");
    }

    protected String getFileContents(final ArtifactHandler handler) throws IOException {
        final StringBuilder sb = new StringBuilder();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(handler.getLocalURL().openStream(), "UTF-8"))) {
            for(String line = reader.readLine(); line != null; line = reader.readLine()) {
                sb.append(line).append('\n');
            }
        }

        return sb.toString();
    }

    public static String getValue(final String xml, final String[] xpath) {
        String value = null;
        int pos = 0;
        for(final String name : xpath) {
            final String element = '<' + name + '>';

            pos = xml.indexOf(element, pos);
            if ( pos == -1 ) {
                final String elementWithAttributes = '<' + name + ' ';
                pos = xml.indexOf(elementWithAttributes, pos);
                if ( pos == -1 ) {
                    break;
                }
            }
            pos = xml.indexOf('>', pos) + 1;
        }
        if ( pos != -1 ) {
            final int endPos = xml.indexOf("</", pos);
            if ( endPos != -1 ) {
                value = xml.substring(pos, endPos).trim();
            }
        }
        return value;
    }
    public static String getLatestSnapshot(final String mavenMetadata) {
        final String timestamp = getValue(mavenMetadata, new String[] {"metadata", "versioning", "snapshot", "timestamp"});
        final String buildNumber = getValue(mavenMetadata, new String[] {"metadata", "versioning", "snapshot", "buildNumber"});

        if ( timestamp != null && buildNumber != null ) {
            return timestamp + '-' + buildNumber;
        }

        return null;
    }

    private static final class DefaultArtifactHandler implements ArtifactProvider {

        private final Logger logger = LoggerFactory.getLogger(this.getClass());

        private volatile File cacheDir;

        private volatile ArtifactProviderContext config;

        @Override
        public String getProtocol() {
            return "*";
        }

        @Override
        public void init(final ArtifactProviderContext config) throws IOException {
            this.cacheDir = config.getCacheDirectory();
            this.config = config;
        }

        @Override
        public void shutdown() {
            this.config = null;
            this.cacheDir = null;
        }

        @Override
        public URL getArtifact(final String url, final String relativeCachePath) {
            logger.debug("Checking url to be local file {}", url);
            // check if this is already a local file
            try {
                final File f = new File(new URL(url).toURI());
                if ( f.exists() ) {
                    this.config.incLocalArtifacts();
                    return f.toURI().toURL();
                }
                return null;
            } catch ( final URISyntaxException ise) {
                // ignore
            } catch ( final IllegalArgumentException iae) {
                // ignore
            } catch ( final MalformedURLException mue) {
                // ignore
            }
            logger.debug("Checking remote url {}", url);
            try {
                // check for url
                if ( url.indexOf(":") == -1 ) {
                    return null;
                }

                final String filePath = (this.cacheDir.getAbsolutePath() + File.separatorChar + relativeCachePath).replace('/', File.separatorChar);
                final File cacheFile = new File(filePath);

                if ( !cacheFile.exists() ) {
                    cacheFile.getParentFile().mkdirs();
                    final URL u = new URL(url);
                    final URLConnection con = u.openConnection();
                    final String userInfo = u.getUserInfo();
                    if (userInfo != null) {
                        con.addRequestProperty("Authorization", "Basic " + Base64.getEncoder().encodeToString(u.toURI().getUserInfo().getBytes("UTF-8")));
                    }
                    con.connect();

                    final InputStream readIS = con.getInputStream();
                    final byte[] buffer = new byte[32768];
                    int l;
                    OutputStream os = null;
                    try {
                        os = new FileOutputStream(cacheFile);
                        while ( (l = readIS.read(buffer)) >= 0 ) {
                            os.write(buffer, 0, l);
                        }
                    } finally {
                        try {
                            readIS.close();
                        } catch ( final IOException ignore) {
                            // ignore
                        }
                        if ( os != null ) {
                            try {
                                os.close();
                            } catch ( final IOException ignore ) {
                                // ignore

                            }
                        }
                    }
                    this.config.incDownloadedArtifacts();
                } else {
                    this.config.incCachedArtifacts();
                }
                return cacheFile.toURI().toURL();
            } catch ( final FileNotFoundException e) {
                logger.trace("File not found here (keep on looking): '{}'", url);
                // Do not report if the file does not exist as we cycle through the various sources
                return null;
            } catch ( final Exception e) {
                logger.info("Artifact not found in one repository", e);
                // ignore for now
                return null;
            }
        }

        @Override
        public String toString() {
            return "DefaultArtifactHandler";
        }
    }
}
