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.DependencyResolveDetails;
import org.gradle.api.artifacts.ModuleVersionSelector;
import org.gradle.api.artifacts.ResolutionStrategy;
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(new Action<Configuration>() {
            @Override
            public void execute(Configuration configuration) {
                configuration.resolutionStrategy(new Action<ResolutionStrategy>() {
                    @Override
                    public void execute(ResolutionStrategy resolutionStrategy) {
                        resolutionStrategy.eachDependency(new Action<DependencyResolveDetails>() {
                            @Override
                            public void execute(DependencyResolveDetails 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.23");
        return rockerCompilerRuntime;
    }

}

@@ -4002,38 +4002,11 @@
 ion.
-resolutionStrategy(new Action%3C
+get
 Reso
@@ -4023,167 +4023,10 @@
 tegy
-%3E
 ()
- %7B%0A                    @Override%0A                    public void execute(ResolutionStrategy resolutionStrategy) %7B%0A                        resolutionStrategy
 .eac
@@ -4094,32 +4094,24 @@
             
-        
 @Override%0A  
@@ -4104,32 +4104,24 @@
   @Override%0A
-        
             
@@ -4208,24 +4208,16 @@
         
-        
 ModuleVe
@@ -4262,32 +4262,24 @@
 equested();%0A
-        
             
@@ -4412,24 +4412,16 @@
         
-  
-      
 details.
@@ -4507,75 +4507,9 @@
     
-        %7D%0A                            %7D%0A                        %7D);
+%7D
 %0A   

Simplify and remove one level of anonymous inner class nesting.