/*
 * 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 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.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(),
                    "-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");
            }

            // 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)
                        .forEach(Javadocs::removeGeneratedDate);
            } catch (IOException e) {
                throw new IllegalStateException("Failed to remove timestamp from generated javadoc html");
            }

        });
    }

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

    public static void removeGeneratedDate(final File file) {
        try {
            final List<String> lines = Stream.of(IO.slurp(file).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";

            // Write the cleaned version to disk
            IO.copy(IO.read(updated), file);

        } catch (IOException e) {
            throw new IllegalStateException(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");
    }
}
