/*
 * 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.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 Exception e) {
                logger.info("Artifact not found in one repository", e);
                // ignore for now
                return null;
            }
        }

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