package io.freefair.gradle.plugins.maven.javadoc;

import java.io.File;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import lombok.Getter;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.plugins.JavaBasePlugin;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.tasks.TaskProvider;
import org.gradle.api.tasks.javadoc.Javadoc;
import org.gradle.external.javadoc.StandardJavadocDocletOptions;

@Getter
public class AggregateJavadocPlugin implements Plugin<Project> {

    private TaskProvider<Javadoc> aggregateJavadoc;

    @Override
    public void apply(Project project) {
        aggregateJavadoc = project.getTasks().register("aggregateJavadoc", Javadoc.class, aggregateJavadoc ->
                aggregateJavadoc.setGroup(JavaBasePlugin.DOCUMENTATION_GROUP)
        );

        project.allprojects(p ->
                p.getPlugins().withType(JavaPlugin.class, jp ->
                        aggregateJavadoc.configure(aj -> {
                            TaskProvider<Javadoc> javadoc = p.getTasks().named(JavaPlugin.JAVADOC_TASK_NAME, Javadoc.class);

                            aj.source(javadoc.map(Javadoc::getSource));

                            if (aj.getClasspath() instanceof ConfigurableFileCollection) {
                                ((ConfigurableFileCollection) aj.getClasspath()).from(javadoc.map(Javadoc::getClasspath));
                            }
                            else {
                                ConfigurableFileCollection classpath = project.files();
                                classpath.from(aj.getClasspath());
                                classpath.from(javadoc.map(Javadoc::getClasspath));
                                aj.setClasspath(classpath);
                            }

                            StandardJavadocDocletOptions options = (StandardJavadocDocletOptions) javadoc.get().getOptions();
                            StandardJavadocDocletOptions aggregateOptions = (StandardJavadocDocletOptions) aj.getOptions();

                            options.getLinks().forEach(link -> {
                                if (!aggregateOptions.getLinks().contains(link)) {
                                    aggregateOptions.getLinks().add(link);
                                }
                            });
                            options.getLinksOffline().forEach(link -> {
                                if (!aggregateOptions.getLinksOffline().contains(link)) {
                                    aggregateOptions.getLinksOffline().add(link);
                                }
                            });
                            options.getJFlags().forEach(jFlag -> {
                                if (!aggregateOptions.getJFlags().contains(jFlag)) {
                                    aggregateOptions.getJFlags().add(jFlag);
                                }
                            });
                        })
                )
        );

        project.afterEvaluate(p -> aggregateJavadoc.configure(aggregateJavadoc -> {
            if (aggregateJavadoc.getDestinationDir() == null) {
                File docsDir = Optional.ofNullable(project.getConvention().findPlugin(JavaPluginConvention.class))
                        .map(JavaPluginConvention::getDocsDir)
                        .orElse(new File(project.getBuildDir(), "docs"));

                aggregateJavadoc.setDestinationDir(new File(docsDir, "aggregateJavadoc"));
            }
        }));
    }
}

@@ -48,148 +48,8 @@
 c;%0A%0A
-import java.io.File;%0Aimport java.util.List;%0Aimport java.util.Optional;%0Aimport java.util.stream.Collectors;%0Aimport java.util.stream.Stream;%0A%0A
 impo
@@ -62,24 +62,24 @@
 bok.Getter;%0A
+
 import org.g
@@ -475,16 +475,103 @@
 tions;%0A%0A
+import java.io.File;%0Aimport java.util.Optional;%0Aimport java.util.concurrent.Callable;%0A%0A
 @Getter%0A
@@ -740,24 +740,25 @@
  project) %7B%0A
+%0A
         aggr
@@ -854,21 +854,19 @@
 vadoc -%3E
-%0A    
+ %7B%0A
         
@@ -930,16 +930,17 @@
 N_GROUP)
+;
 %0A       
@@ -932,32 +932,561 @@
 GROUP);%0A        
+    aggregateJavadoc.getConventionMapping().map(%22destinationDir%22, new Callable%3CObject%3E() %7B%0A                @Override%0A                public Object call() %7B%0A                    File docsDir = Optional.ofNullable(project.getConvention().findPlugin(JavaPluginConvention.class))%0A                            .map(JavaPluginConvention::getDocsDir)%0A                            .orElse(new File(project.getBuildDir(), %22docs%22));%0A                    return new File(docsDir, %22aggregateJavadoc%22);%0A                %7D%0A            %7D);%0A        %7D
 );%0A%0A        proj
@@ -3641,528 +3641,8 @@
   );
-%0A%0A        project.afterEvaluate(p -%3E aggregateJavadoc.configure(aggregateJavadoc -%3E %7B%0A            if (aggregateJavadoc.getDestinationDir() == null) %7B%0A                File docsDir = Optional.ofNullable(project.getConvention().findPlugin(JavaPluginConvention.class))%0A                        .map(JavaPluginConvention::getDocsDir)%0A                        .orElse(new File(project.getBuildDir(), %22docs%22));%0A%0A                aggregateJavadoc.setDestinationDir(new File(docsDir, %22aggregateJavadoc%22));%0A            %7D%0A        %7D));
 %0A   

fix aggregateJavadoc destinationDir