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

import lombok.Data;
import org.apache.openejb.loader.Files;
import org.apache.openejb.loader.IO;
import org.apache.openejb.util.Join;
import org.apache.openejb.util.Pipe;

import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.apache.openejb.loader.Files.mkdirs;

/**
 * For each git repo (source) it will collects the `src/main/java` contents
 * into one large source tree and use the Javadoc proccessor directly in code
 * to (with Asciidoclet configured) to generate a single javadoc for that repo.
 *
 * The examples/ directory for each repo will be filtered out and not included
 * in the final aggregated javadoc.
 */
public class Javadocs {

    private final Sources sources;
    private final List<JavadocSource> javadocSources = new ArrayList<>();

    public Javadocs(final Sources sources) {
        this.sources = sources;
    }

    /**
     * Method is called for each git repo configured
     * as a codebase that contributes to the documentation
     *
     * This is currently active branches of TomEE, but will
     * be other sources in the future such as Sheldon
     * and Chatterbox
     *
     * This method recurssively walks the already cloned
     * git repo (the Source) and collects all `src/main/java`
     * directories.
     *
     * All the files in these directories are aggregated into
     * one single director at `target/<source.name>-java`.
     * For example `target/tomee-8.0-java`
     *
     * We then run the javadoc processor on `target/<source.name>-java`
     * and ensure all generated javadoc is placed at:
     *
     *  - `<sources.generated>/<source.name>/javadoc/`
     *
     * For example if the Source instance represents TomEE 8.0
     * and the Sources.getGenerated() returns `target/site-1.0-SNAPSHOT`
     * we would generate all the javadoc into this location:
     *
     *  - `target/site-1.0-SNAPSHOT/tomee-8.0/javadoc`
     *
     * @param source
     */
    public void prepare(final Source source) {
        final File javaSources = mkdirs(new File(String.format("target/javadocs/%s-src", source.getName())));

        copySource(source, source, javaSources);
        for (final Source related : source.getRelated()) {
            copySource(source, related, javaSources);
        }

        // This part will be completed later when the perform stage is executed
        source.addPerform(() -> {
            final File javadocOutput = sources.getGeneratedDestFor(source, "javadoc");
            final ProcessBuilder cmd = new ProcessBuilder(
                    getJavadocCommand().getAbsolutePath(),
                    "-tag",
                    "example.en:a:Examples (en):",
                    "-tag",
                    "example.es:a:Examples (es):",
                    "-tag",
                    "example.pt:a:Examples (pt):",
                    "-sourcepath",
                    javaSources.getAbsolutePath(),
                    "-d",
                    javadocOutput.getAbsolutePath()
            );

            Stream.of(javaSources.listFiles())
                    .filter(File::isDirectory)
                    .forEach(file -> {
                        cmd.command().add("-subpackages");
                        cmd.command().add(file.getName());
                    });

            try {
                final Process process = cmd.start();
                Pipe.pipe(process);
                process.waitFor();
            } catch (IOException e) {
                throw new IllegalStateException("Command failed");
            } catch (InterruptedException e) {
                Thread.interrupted();
                throw new IllegalStateException("Command failed");
            }

            final String favicon = getFavicon(source);

            // Scrub generated timestamps as it causes 26k needless file updates
            // on the svn commit for every time the generator runs
            try {
                java.nio.file.Files.walk(javadocOutput.toPath())
                        .map(Path::toFile)
                        .filter(File::isFile)
                        .filter(this::isHtml)
                        .map(Content::from)
                        .map(Javadocs::removeGeneratedDate)
                        .map(content -> addFavicon(content, favicon))
                        .forEach(Content::write);
            } catch (IOException e) {
                throw new IllegalStateException("Failed to update generated javadoc html");
            }

        });
    }

    private String getFavicon(final Source source) {
        if (source.getName().startsWith("jakarta")) {
            return "/img/jakarta-favicon.ico";
        } else if (source.getName().startsWith("microprofile")) {
            return "/img/microprofile-favicon.png";
        } else {
            return "/favicon.png";
        }
    }

    public List<JavadocSource> getJavadocSources() {
        return javadocSources;
    }

    private static Content removeGeneratedDate(final Content content) {
        final List<String> lines = Stream.of(content.content.split("\n"))
                .filter(line -> !line.contains("<!-- Generated by javadoc"))
                .filter(line -> !line.contains("<meta name=\"date\" content=\""))
                .collect(Collectors.toList());

        final String updated = Join.join("\n", lines) + "\n";

        return content.modified(updated);
    }

    private static Content addFavicon(final Content content, final String favicon) {
        final String link = String.format("%n<link rel=\"shortcut icon\" href=\"%s\">%n", favicon);
        return content.modified(content.content.replace("</head>", link + "</head>"));
    }

    @Data
    @lombok.AllArgsConstructor
    private static class Content {
        private final File file;
        private final String content;

        public Content modified(final String newContent) {
            return new Content(file, newContent);
        }

        public void write() {
            try {
                IO.copy(IO.read(content), file);
            } catch (IOException e) {
                throw new UncheckedIOException("Unable to write file: " + file.getAbsolutePath(), e);
            }
        }

        public static Content from(final File file) {
            try {
                return new Content(file, IO.slurp(file));
            } catch (IOException e) {
                throw new UncheckedIOException("Unable to read file: " + file.getAbsolutePath(), e);
            }
        }
    }

    private void copySource(final Source parent, final Source source, final File javaSources) {
        final JavadocSources javadocSources = new JavadocSources();
        source.setComponent(JavadocSources.class, javadocSources);

        final Predicate<String> wanted = wanted(parent, source);

        try {
            java.nio.file.Files.walk(source.getDir().toPath())
                    .map(Path::toFile)
                    .filter(File::isFile)
                    .filter(this::isJava)
                    .filter(source.getJavadocFilter()::include)
                    .filter(source.getJavadocFilter()::exclude)
                    .forEach(file -> {
                        try {
                            final String relativePath = file.getAbsolutePath().replaceAll(".*/src/main/java/", "");

                            if (!wanted.test(relativePath)) return;

                            final File dest = new File(javaSources, relativePath);
                            Files.mkdirs(dest.getParentFile());
                            IO.copy(file, dest);
                            javadocSources.add(new JavadocSource(relativePath, dest));
                        } catch (IOException e) {
                            throw new IllegalStateException(e);
                        }
                    });
        } catch (IOException e) {
            throw new IllegalStateException("Failed to aggregate java sources");
        }
    }

    private Predicate<String> wanted(final Source parent, final Source source) {
        if (source.getJavadocPackages() != null) return source.getJavadocPackages().asPredicate();
        if (parent.getJavadocPackages() != null) return parent.getJavadocPackages().asPredicate();
        return s -> true;
    }

    public static File getJavadocCommand() {

        final File java_home = System.getenv("JAVA_HOME") != null ? new File(System.getenv("JAVA_HOME")) : new File("");
        final File javaHome = new File(System.getProperty("java.home"));

        final Supplier<File>[] locations = new Supplier[]{
                () -> new File(java_home, "bin/javadoc"),
                () -> new File(java_home, "bin/javadoc.exe"),
                () -> new File(java_home.getParentFile(), "bin/javadoc"),
                () -> new File(java_home.getParentFile(), "bin/javadoc.exe"),
                () -> new File(javaHome, "bin/javadoc"),
                () -> new File(javaHome, "bin/javadoc.exe"),
                () -> new File(javaHome.getParentFile(), "bin/javadoc"),
                () -> new File(javaHome.getParentFile(), "bin/javadoc.exe"),
        };

        return Stream.of(locations)
                .map(Supplier::get)
                .filter(File::exists)
                .filter(File::canExecute)
                .findFirst().orElseThrow(() -> new IllegalStateException("Cannot find javadoc command"));
    }

    public static void main(String[] args) {
    }

    private static void copy(final File file, File javaSources) {
    }

    private boolean isJava(final File file) {
        return file.getName().endsWith(".java");
    }

    private boolean isHtml(final File file) {
        return file.getName().endsWith(".html");
    }
}
