package emma;

import org.gradle.api.*
import org.gradle.api.tasks.testing.Test
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.Input
import com.vladium.emma.instr.InstrProcessor
import com.vladium.emma.report.ReportProcessor
import org.gradle.api.tasks.InputFiles
import com.vladium.util.XProperties;

/**
 *
 * @author Luke Taylor
 */
class EmmaPlugin implements Plugin<Project> {

	void apply(Project project) {
		Project rootProject = project.rootProject
		def emmaMetaDataFile = "${rootProject.buildDir}/emma/emma.em"
		def emmaCoverageFile = "${rootProject.buildDir}/emma/emma.ec"

		if (project.configurations.findByName('emma_rt') == null) {
			project.configurations.create('emma_rt')
			project.dependencies {
				emma_rt 'emma:emma:2.0.5312'
			}
		}

		project.task('emmaInstrument') {
			dependsOn project.classes

			doFirst {
				InstrProcessor processor = InstrProcessor.create ();
				String[] classesDirPath = [project.sourceSets.main.output.classesDir.absolutePath]

				processor.setInstrPath(classesDirPath, false);
				processor.setOutMode(InstrProcessor.OutMode.OUT_MODE_COPY);
				processor.setInstrOutDir("${project.buildDir}/emma/classes");
				processor.setMetaOutFile(emmaMetaDataFile);
				processor.setMetaOutMerge(true);
				//processor.setInclExclFilter (null);
				processor.run();
			}
		}

		// Modify test tasks in the project to generate coverage data
		project.afterEvaluate {
			if (project.hasProperty('coverage') && ['on','true'].contains(project.properties.coverage)) {
				project.tasks.withType(Test.class).each { task ->
					task.dependsOn project.emmaInstrument
					task.configure() {
						jvmArgs '-Dsec.log.level=DEBUG', "-Demma.coverage.out.file=$emmaCoverageFile"
						jvmArgs '-Demma.verbosity.level=quiet'
					}
					task.doFirst {
						classpath = project.files("${project.buildDir}/emma/classes") + project.configurations.emma_rt + classpath
					}
				}
			}
		}

		List<Task> reportTasks = rootProject.getTasksByName('coverageReport', false) as List;
		CoverageReport task;

		if (reportTasks.isEmpty()) {
			task = rootProject.tasks.create('coverageReport', CoverageReport.class);
			task.dataPath = [emmaMetaDataFile, emmaCoverageFile];
		} else {
			task = reportTasks[0];
		}

		task.modules.add(project);
	}
}

class CoverageReport extends DefaultTask {
	@Input
	List<Project> modules = [];

	@Input
	String[] dataPath;

	@TaskAction
	void generateReport() {
		def buildDir = project.rootProject.buildDir

		if (!buildDir.exists()) {
			throw new GradleException("No coverage data. Run gradle with -Pcoverage=on if using coverageReport");
		}

		ReportProcessor processor = ReportProcessor.create ();
		processor.setDataPath(dataPath)

		def srcPath = []
		modules.each {module->
			module.sourceSets.main.java.srcDirs.each {
				srcPath.add(it.absolutePath)
			}
		}

		processor.setSourcePath(srcPath as String[]);


		def types = ['txt', 'html']
		processor.setReportTypes(types as String[]);
		XProperties properties = new XProperties();
		properties.setProperty('report.html.out.file', "$buildDir/emma/coverage.html");
		properties.setProperty('report.txt.out.file', "$buildDir/emma/coverage.txt");
		processor.setPropertyOverrides(properties)

		processor.run()
	}
}
