package nu.studer.gradle.rocker;

import org.gradle.api.Action;
import org.gradle.api.NamedDomainObjectContainer;
import org.gradle.api.NamedDomainObjectFactory;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.ModuleVersionSelector;
import org.gradle.api.plugins.BasePlugin;
import org.gradle.api.plugins.JavaBasePlugin;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.SourceSetContainer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static nu.studer.gradle.rocker.StringUtils.capitalize;

@SuppressWarnings("unused")
public class RockerPlugin implements Plugin<Project> {

    private static final Logger LOGGER = LoggerFactory.getLogger(RockerPlugin.class);

    @Override
    public void apply(final Project project) {
        // apply Java base plugin, making it possible to also use the rocker plugin for Android builds
        project.getPlugins().apply(JavaBasePlugin.class);

        // allow to configure the rocker version via extension property
        RockerVersion.applyDefaultVersion(project);

        // use the configured rocker version on all rocker dependencies
        enforceRockerVersion(project);

        // add rocker DSL extension
        NamedDomainObjectContainer<RockerConfig> container = project.container(RockerConfig.class, new NamedDomainObjectFactory<RockerConfig>() {
            @Override
            public RockerConfig create(String name) {
                return new RockerConfig(name, project);
            }
        });
        project.getExtensions().add("rocker", container);

        // create configuration for the runtime classpath of the rocker compiler (shared by all rocker configuration domain objects)
        final Configuration configuration = createRockerCompilerRuntimeConfiguration(project);

        // create a rocker task for each rocker configuration domain object
        container.all(new Action<RockerConfig>() {
            @Override
            public void execute(RockerConfig config) {
                // create rocker task
                RockerCompile rocker = project.getTasks().create(config.getCompileTaskName(), RockerCompile.class);
                rocker.setGroup("Rocker");
                rocker.setDescription("Invokes the Rocker template engine.");
                rocker.setConfig(config);
                rocker.setRuntimeClasspath(configuration);

                // clean sources generated by rocker task as part of the 'clean' life-cycle task
                String cleanRockerSources = "clean" + capitalize(rocker.getName());
                project.getTasks().getByName(BasePlugin.CLEAN_TASK_NAME).dependsOn(cleanRockerSources);
                rocker.mustRunAfter(cleanRockerSources);

                // wire task dependencies such that the rocker task creates the sources before the corresponding Java compile task compiles them and
                // add the rocker-runtime to the compile configuration in order to be able to compile the generated sources
                SourceSetContainer sourceSets = project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets();
                SourceSet sourceSet = sourceSets.findByName(config.name);
                if (sourceSet != null) {
                    project.getTasks().getByName(sourceSet.getCompileJavaTaskName()).dependsOn(rocker);
                    project.getDependencies().add(sourceSet.getCompileConfigurationName(), "com.fizzed:rocker-runtime");
                }
            }
        });
    }

    private void enforceRockerVersion(final Project project) {
        project.getConfigurations().all(configuration ->
            configuration.getResolutionStrategy().eachDependency(details -> {
                ModuleVersionSelector requested = details.getRequested();
                if (requested.getGroup().equals("com.fizzed") && requested.getName().startsWith("rocker-")) {
                    details.useVersion(RockerVersion.fromProject(project).asString());
                }
            })
        );
    }

    private Configuration createRockerCompilerRuntimeConfiguration(Project project) {
        Configuration rockerCompilerRuntime = project.getConfigurations().create("rockerCompiler");
        rockerCompilerRuntime.setDescription("The classpath used to invoke the Rocker template engine. Add your additional dependencies here.");
        project.getDependencies().add(rockerCompilerRuntime.getName(), "com.fizzed:rocker-compiler");
        project.getDependencies().add(rockerCompilerRuntime.getName(), "org.slf4j:slf4j-simple:1.7.25");
        return rockerCompilerRuntime;
    }

}

@@ -53,112 +53,34 @@
 api.
-Action;%0Aimport org.gradle.api.NamedDomainObjectContainer;%0Aimport org.gradle.api.NamedDomainObjectFactory
+NamedDomainObjectContainer
 ;%0Aim
@@ -1359,152 +1359,14 @@
 s, n
-ew NamedDomainObjectFactory%3CRockerConfig%3E() %7B%0A            @Override%0A            public RockerConfig create(String name) %7B%0A                return
+ame -%3E
  new
@@ -1397,33 +1397,8 @@
 ect)
-;%0A            %7D%0A        %7D
 );%0A 
@@ -1786,118 +1786,20 @@
 all(
-new Action%3CRockerC
+c
 onfig
-%3E()
+ -%3E
  %7B%0A
-            @Override%0A            public void execute(RockerConfig config) %7B%0A    
     
@@ -1824,28 +1824,24 @@
 rocker task%0A
-    
             
@@ -1944,55 +1944,8 @@
 s);%0A
-                rocker.setGroup(%22Rocker%22);%0A    
     
@@ -2010,32 +2010,67 @@
  engine.%22);%0A    
+        rocker.setGroup(%22Rocker%22);%0A
             rock
@@ -2095,36 +2095,32 @@
 g);%0A            
-   
- 
 rocker.setRuntim
@@ -2143,28 +2143,24 @@
 guration);%0A%0A
-    
             
@@ -2252,20 +2252,16 @@
         
-   
- 
 String c
@@ -2316,28 +2316,24 @@
 getName());%0A
-    
             
@@ -2428,28 +2428,24 @@
             
-   
- 
 rocker.mustR
@@ -2470,28 +2470,24 @@
 rSources);%0A%0A
-    
             
@@ -2627,28 +2627,24 @@
             
-   
- 
 // add the r
@@ -2739,20 +2739,16 @@
 sources%0A
-    
         
@@ -2866,36 +2866,32 @@
 ();%0A            
-   
- 
 SourceSet source
@@ -2940,28 +2940,24 @@
             
-    
 if (sourceSe
@@ -2977,36 +2977,32 @@
                 
-   
- 
 project.getTasks
@@ -3069,20 +3069,16 @@
 ocker);%0A
-    
         
@@ -3186,34 +3186,16 @@
 time%22);%0A
-                %7D%0A
         

Use more lambdas