package io.freefair.gradle.plugins.javadoc;

import lombok.Setter;
import org.gradle.api.DefaultTask;
import org.gradle.api.JavaVersion;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.ResolvedArtifact;
import org.gradle.api.artifacts.component.ComponentIdentifier;
import org.gradle.api.artifacts.component.ModuleComponentIdentifier;
import org.gradle.api.provider.PropertyState;
import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.javadoc.Javadoc;
import org.gradle.external.javadoc.MinimalJavadocOptions;
import org.gradle.external.javadoc.StandardJavadocDocletOptions;

/**
 * @author Lars Grefer
 */
public class ConfigureJavadocLinks extends DefaultTask {

    @Setter
    private Javadoc javadoc;

    private final PropertyState<Configuration> configuration = getProject().property(Configuration.class);

    private final PropertyState<Boolean> useHttps = getProject().property(Boolean.class);

    private final PropertyState<JavaVersion> javaVersion = getProject().property(JavaVersion.class);

    @TaskAction
    public void configureJavadocLinks() {

        String protocol = isUseHttps() ? "https" : "http";

        switch (getJavaVersion()) {
            case VERSION_1_5:
                addLink(protocol + "://docs.oracle.com/javase/5/docs/api/");
                break;
            case VERSION_1_6:
                addLink(protocol + "://docs.oracle.com/javase/6/docs/api/");
                break;
            case VERSION_1_7:
                addLink(protocol + "://docs.oracle.com/javase/7/docs/api/");
                break;
            default:
                getLogger().warn("Unknown java version {}", javaVersion);
            case VERSION_1_8:
                addLink(protocol + "://docs.oracle.com/javase/8/docs/api/");
                break;
        }

        for (ResolvedArtifact resolvedArtifact : getConfiguration().getResolvedConfiguration().getResolvedArtifacts()) {
            ComponentIdentifier componentIdentifier = resolvedArtifact.getId().getComponentIdentifier();

            if (componentIdentifier instanceof ModuleComponentIdentifier) {
                ModuleComponentIdentifier moduleComponentIdentifier = (ModuleComponentIdentifier) componentIdentifier;
                String group = moduleComponentIdentifier.getGroup();
                String artifact = moduleComponentIdentifier.getModule();
                String version = moduleComponentIdentifier.getVersion();

                String wellKnownLink = findWellKnownLink(group, artifact, version);
                if (wellKnownLink != null) {
                    getLogger().info("Using well known link '{}' for '{}:{}:{}'", wellKnownLink, group, artifact, version);
                    addLink(wellKnownLink);
                    break;
                } else {
                    getLogger().info("Using javadoc.io link for '{}:{}:{}'", group, artifact, version);
                    String javadocIoLink = String.format("%s://static.javadoc.io/%s/%s/%s/", protocol, group, artifact, version);
                    addLink(javadocIoLink);
                }
            }
        }
    }

    private String findWellKnownLink(String group, String artifact, String version) {
        if (group.equals("org.springframework") && artifact.startsWith("spring-")) {
            return "http://docs.spring.io/spring/docs/" + version + "/javadoc-api/";
        } else if (group.equals("org.springframework.boot")) {
            return "http://docs.spring.io/spring-boot/docs/" + version + "/api/";
        }
        return null;
    }

    private void addLink(String baseUrl) {
        MinimalJavadocOptions options = javadoc.getOptions();
        if (options instanceof StandardJavadocDocletOptions) {
            StandardJavadocDocletOptions docletOptions = (StandardJavadocDocletOptions) options;
            if (!docletOptions.getLinks().contains(baseUrl)) {
                getLogger().debug("Adding '{}' to {}", baseUrl, javadoc);
                docletOptions.links(baseUrl);
                setDidWork(true);
            } else {
                getLogger().info("Not adding '{}' to {} because it's already present", baseUrl, javadoc);
            }
        }
    }

    @Input
    public boolean isUseHttps() {
        return useHttps.get();
    }

    public void setUseHttps(Provider<Boolean> useHttps) {
        this.useHttps.set(useHttps);
    }

    public void setUseHttps(boolean useHttps) {
        this.useHttps.set(useHttps);
    }

    @InputFiles
    public Configuration getConfiguration() {
        return configuration.get();
    }

    public void setConfiguration(Provider<Configuration> configuration) {
        this.configuration.set(configuration);
    }

    public void setConfiguration(Configuration configuration) {
        this.configuration.set(configuration);
    }

    @Input
    public JavaVersion getJavaVersion() {
        return javaVersion.get();
    }

    public void setJavaVersion(Provider<JavaVersion> javaVersion) {
        this.javaVersion.set(javaVersion);
    }

    public void setJavaVersion(JavaVersion javaVersion) {
        this.javaVersion.set(javaVersion);
    }
}

@@ -973,99 +973,8 @@
 );%0A%0A
-    private final PropertyState%3CBoolean%3E useHttps = getProject().property(Boolean.class);%0A%0A
     
@@ -1134,68 +1134,8 @@
  %7B%0A%0A
-        String protocol = isUseHttps() ? %22https%22 : %22http%22;%0A%0A
     
@@ -1216,36 +1216,30 @@
     addLink(
-protocol + %22
+%22https
 ://docs.orac
@@ -1340,36 +1340,30 @@
     addLink(
-protocol + %22
+%22https
 ://docs.orac
@@ -1464,36 +1464,30 @@
     addLink(
-protocol + %22
+%22https
 ://docs.orac
@@ -1554,15 +1554,24 @@
     
-default
+case VERSION_1_8
 :%0A  
@@ -1588,64 +1588,84 @@
     
-getLogger().warn(%22Unknown java version %7B%7D%22, javaVersion)
+addLink(%22https://docs.oracle.com/javase/8/docs/api/%22);%0A                break
 ;%0A  
@@ -1681,33 +1681,33 @@
  case VERSION_1_
-8
+9
 :%0A              
@@ -1720,20 +1720,14 @@
 ink(
-protocol + %22
+%22https
 ://d
@@ -1740,33 +1740,33 @@
 acle.com/javase/
-8
+9
 /docs/api/%22);%0A  
@@ -1778,32 +1778,127 @@
          break;%0A
+            default:%0A                getLogger().warn(%22Unknown java version %7B%7D%22, javaVersion);%0A
         %7D%0A%0A     
@@ -3041,17 +3041,20 @@
 format(%22
-%25
+http
 s://stat
@@ -3082,18 +3082,8 @@
 s/%22,
- protocol,
  gro
@@ -3386,32 +3386,33 @@
     return %22http
+s
 ://docs.spring.i
@@ -3543,16 +3543,17 @@
 rn %22http
+s
 ://docs.
@@ -4284,285 +4284,8 @@
  %7D%0A%0A
-    @Input%0A    public boolean isUseHttps() %7B%0A        return useHttps.get();%0A    %7D%0A%0A    public void setUseHttps(Provider%3CBoolean%3E useHttps) %7B%0A        this.useHttps.set(useHttps);%0A    %7D%0A%0A    public void setUseHttps(boolean useHttps) %7B%0A        this.useHttps.set(useHttps);%0A    %7D%0A%0A
     

Use https for javadoc links and add java 9 link