/*
 * 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.meecrowave.doc.generator;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;

import static java.util.Arrays.asList;
import static java.util.Optional.ofNullable;
import static java.util.stream.Collectors.toList;

// helper to generate the download table content
public class Downloads {
    private static final SAXParserFactory FACTORY = SAXParserFactory.newInstance();
    private static final String MVN_BASE = "https://repo.maven.apache.org/maven2/";

    private static final String DIST_RELEASE = "https://dist.apache.org/repos/dist/release/openwebbeans/meecrowave/";
    private static final String ARCHIVE_RELEASE = "https://archive.apache.org/dist/openwebbeans/meecrowave/";
    private static final String MIRROR_RELEASE = "http://www.apache.org/dyn/closer.lua/openwebbeans/meecrowave/";

    private static final long MEGA_RATIO = 1024 * 1024;
    private static final long KILO_RATIO = 1024;

    static {
        FACTORY.setNamespaceAware(false);
        FACTORY.setValidating(false);
    }

    private Downloads() {
        // no-op
    }

    public static void main(final String[] args) {
        doMain(System.out);
    }

    public static void doMain(final PrintStream stream) {
        System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "32");

        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.of("UTC"));

        Stream.of(
                Stream.of("org/apache/meecrowave/meecrowave")
                        .flatMap(Downloads::toVersions)
                        .map(v -> v.extensions("zip"))
                        .map(v -> v.classifiers("source-release")),
                versionStream("meecrowave-core")
                        .map(v -> v.classifiers("", "runner"))
                        .map(v -> v.extensions("jar")))
              .flatMap(s -> s)
              .flatMap(Downloads::toDownloadable)
              .parallel()
              .map(Downloads::fillDownloadable)
              .filter(Objects::nonNull)
              .sorted((o1, o2) -> {
                    final int versionComp = o2.version.compareTo(o1.version);
                    if (versionComp != 0) {
                        if (o2.version.startsWith(o1.version) && o2.version.contains("-M")) { // milestone
                            return -1;
                        }
                        if (o1.version.startsWith(o2.version) && o1.version.contains("-M")) { // milestone
                            return 1;
                        }
                        return versionComp;
                    }


                    final int nameComp = o1.name.compareTo(o2.name);
                    if (nameComp != 0) {
                        return nameComp;
                    }

                    final long dateComp = o2.date.compareTo(o1.date);
                    if (dateComp != 0) {
                        return (int) dateComp;
                    }

                    return o1.url.compareTo(o2.url);
                })
              .collect(toList())
              .forEach(d ->
                        stream.println("" +
                                "|" + d.name + (d.classifier.isEmpty() ? "" : (" " + d.classifier)).replace("source-release", "Source Release") +
                                "|" + d.version +
                                "|" + dateFormatter.format(d.date) +
                                "|" + d.size +
                                "|" + d.format +
                                "| " + d.url + "[icon:download[] " + d.format + "] " +
                                (d.sha512 != null?  d.sha512 + "[icon:download[] sha512] " : d.sha1 + "[icon:download[] sha1] ") +
                                d.asc + "[icon:download[] asc]"));
    }

    private static Download fillDownloadable(final Download download) {
        try {
            final URL url = new URL(download.mavenCentralUrl);
            final HttpURLConnection connection = HttpURLConnection.class.cast(url.openConnection());
            connection.setConnectTimeout((int) TimeUnit.SECONDS.toMillis(30));
            final int responseCode = connection.getResponseCode();
            if (responseCode != HttpURLConnection.HTTP_OK) {
                if (HttpURLConnection.HTTP_NOT_FOUND != responseCode) {
                    System.err.println("Got " + responseCode + " for " + download.url);
                }
                return null;
            }

            long lastMod = connection.getHeaderFieldDate("Last-Modified", 0);
            download.date = Instant.ofEpochMilli(lastMod);

            download.size = toSize(ofNullable(connection.getHeaderField("Content-Length"))
                    .map(Long::parseLong).orElse(0L), ofNullable(connection.getHeaderField("Accept-Ranges")).orElse("bytes"));

            connection.getInputStream().close();
        } catch (final IOException e) {
            e.printStackTrace();
            return null;
        }
        return download;
    }

    private static String toSize(final long length, final String bytes) {
        if (!"bytes".equalsIgnoreCase(bytes)) {
            throw new IllegalArgumentException("Not handled unit: " + bytes);
        }
        final long meg = length / MEGA_RATIO;
        final long kilo = (length - (meg * MEGA_RATIO)) / KILO_RATIO;
        return (meg > 0 ? meg + " MB " : "") + (kilo > 0 ? kilo + " kB" : "");
    }

    private static Stream<Version> versionStream(final String artifactId) {
        return Stream.of("org/apache/meecrowave/" + artifactId)
                .flatMap(Downloads::toVersions);
    }

    private static Stream<Download> toDownloadable(final Version version) {
        final String base = version.base;
        final String artifactId = base.substring(base.lastIndexOf('/') + 1, base.length());
        final String artifactBase = version.base + "/" + version.version + "/" + artifactId + "-" + version.version;
        return version.extensions.stream()
                .flatMap(e -> (version.classifiers.isEmpty() ? Stream.of(new ArtifactDescription("", e)) : version.classifiers.stream().map(c -> new ArtifactDescription(c, e))))
                .map(a -> toDownload(artifactId, a.classifier, version.version, a.extension, artifactBase + (a.classifier.isEmpty() ? '.' + a.extension : ('-' + a.classifier + '.' + a.extension))));
    }

    private static Download toDownload(final String artifactId, final String classifier, final String version, final String format, String artifactUrl) {
        String url = DIST_RELEASE + version + "/" + artifactId + "-" + version + "-" + classifier + "." + format;
        String downloadUrl;
        String sha512 = null;
        if (urlExists(url)) {
            // artifact exists on dist.a.o
            downloadUrl = MIRROR_RELEASE + version + "/" + artifactId + "-" + version + "-" + classifier + "." + format;
        }
        else {
            url = ARCHIVE_RELEASE + version + "/" + artifactId + "-" + version + "-" + classifier + "." + format;
            if (urlExists(url)) {
                // artifact exists on archive.a.o
                downloadUrl = url;
            }
            else {
                // falling back to Maven URL
                downloadUrl = artifactUrl;
                url = artifactUrl;
            }
        }

        if (urlExists(url + ".sha512")) {
            sha512 = url + ".sha512";
        }

        return new Download(
                Character.toUpperCase(artifactId.charAt(0)) + artifactId.substring(1).replace('-', ' '),
                classifier,
                version,
                format,
                downloadUrl,
                url + ".sha1",
                sha512,
                url + ".asc",
                artifactUrl);
    }

    private static boolean urlExists(String urlString) {
        try {
            URL url = new URL(urlString);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("HEAD");
            conn.setUseCaches(false);
            return conn.getResponseCode() == HttpURLConnection.HTTP_OK;
        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static Stream<Version> toVersions(final String baseUrl) {
        final QuickMvnMetadataParser handler = new QuickMvnMetadataParser();
        final String base = MVN_BASE + baseUrl;
        try (final InputStream stream = new URL(base + "/maven-metadata.xml").openStream()) {
            final SAXParser parser = FACTORY.newSAXParser();
            parser.parse(stream, handler);
            return handler.foundVersions.stream().map(v -> new Version(base, v)).parallel();
        } catch (final Exception e) {
            e.printStackTrace();
            return Stream.empty();
        }
    }

    public static class Version {
        private final String base;
        private final String version;
        private final Collection<String> classifiers = new ArrayList<>();
        private final Collection<String> extensions = new ArrayList<>();

        public Version(final String base, final String version) {
            this.base = base;
            this.version = version;
        }

        private Version extensions(final String... values) {
            extensions.addAll(asList(values));
            return this;
        }

        private Version classifiers(final String... values) {
            classifiers.addAll(asList(values));
            return this;
        }
    }

    public static class ArtifactDescription {
        private final String classifier;
        private final String extension;

        private ArtifactDescription(final String classifier, final String extension) {
            this.classifier = classifier;
            this.extension = extension;
        }
    }

    public static class Download {
        private final String name;
        private final String classifier;
        private final String version;
        private final String format;
        private final String mavenCentralUrl;
        private final String url;
        private final String sha1;
        private final String sha512;
        private final String asc;
        private Instant date;
        private String size;

        public Download(final String name, final String classifier, final String version,
                        final String format, final String url, final String sha1, final String sha512,
                        final String asc, String mavenCentralUrl) {
            this.name = name;
            this.classifier = classifier;
            this.version = version;
            this.format = format;
            this.url = url;
            this.sha1 = sha1;
            this.sha512 = sha512;
            this.asc = asc;
            this.mavenCentralUrl = mavenCentralUrl;
        }
    }

    private static class QuickMvnMetadataParser extends DefaultHandler {
        private boolean versioning = false;
        private boolean versions = false;
        private StringBuilder version;
        private final Collection<String> foundVersions = new ArrayList<>();

        @Override
        public void startElement(final String uri, final String localName,
                                 final String name, final Attributes attributes) throws SAXException {
            if ("versioning".equalsIgnoreCase(name)) {
                versioning = true;
            } else if ("versions".equalsIgnoreCase(name)) {
                versions = true;
            } else if (versioning && versions && "version".equalsIgnoreCase(name)) {
                version = new StringBuilder();
            }
        }

        @Override
        public void characters(final char[] ch, final int start, final int length) throws SAXException {
            if (version != null) {
                version.append(new String(ch, start, length));
            }
        }

        public void endElement(final String uri, final String localName, final String name) throws SAXException {
            if ("versioning".equalsIgnoreCase(name)) {
                versioning = false;
            } else if ("versions".equalsIgnoreCase(name)) {
                versions = false;
            } else if ("version".equalsIgnoreCase(name)) {
                foundVersions.add(version.toString());
            }
        }
    }
}
