// Plugin declaration

apply plugin: 'asciidoctor'
apply plugin: 'eclipse'
apply plugin: 'findbugs'
apply plugin: 'jacoco'
apply plugin: 'java'
apply plugin: 'jdepend'
apply plugin: 'maven-publish'
apply plugin: 'vagrant'
apply plugin: 'wrapper'

import org.apache.tools.ant.filters.FixCrLfFilter
import org.apache.tools.ant.filters.ReplaceTokens

// Basic settings

group = 'at.uibk.dbis'
version = '0.2.6-SNAPSHOT'

description = 'PhD project of Nikolaus Krismer'

// Upgrade as soon as findbugs 3.0 is available (this version supports JDK8)
//sourceCompatibility=JavaVersion.VERSION_1_8
//targetCompatibility=JavaVersion.VERSION_1_8
sourceCompatibility=JavaVersion.VERSION_1_7
targetCompatibility=JavaVersion.VERSION_1_7

/*
 * Version handling:
 *
 * By default the version set in the version property is used (specified above)
 * The build distinguishes between SNAPSHOT and RELEASE versions. A snapshot version
 * has to end with ".SNAPSHOT" a release version does not. The default version
 * (set above) should always end with "-SNAPSHOT", so that by default only snapshots
 * are built (and used for deployment to testservers and maven repositories)
 *
 * To build releases there are two recommended ways:
 * Start the gradle build with an explicitly given releaseVersion. This can be done
 * by appending a releseVersion parameter to the gradle executable:
 *   ./gradlew -PreleaseVersion=0.2.3 clean daily publish
 * The other possibility is to include the release task in the build gradle tasks:
 *   ./gradlew clean daily publish release
 * In this case the version number specified above is used without the "-SNAPSHOT" part.
 *
 * To check if a release or snapshot version is build a string indicating it is print
 * at the very start of the build process (e.g "Building SNAPSHOT version 0.2.3-SNAPSHOT" or
 * "Building RELEASE version 0.2.3")
 */

ext {
	isRelease = false
}

if (!version.matches(~/[0-9\.]*(-SNAPSHOT)?/)) {
	throw new GradleException("Invalid version number '$version'.")
}

if (project.hasProperty('releaseVersion')) {
	version = releaseVersion;
	isRelease = true;
	if (!version.matches(~/[0-9\.]*/)) {
		throw new GradleException("Invalid relese version number '$version' given.")
	}
}

gradle.taskGraph.whenReady {taskGraph ->
	if (!isRelease && taskGraph.hasTask(release)) {
		version = version.substring(0, version.indexOf('-SNAPSHOT'))
	}

	if (version.endsWith('-SNAPSHOT')) {
		println "Building SNAPSHOT version $version"
	} else {
		println "Building RELEASE version $version"
		isRelease = true;
	}

	// fixes lazy versioning for maven-publish plugin
	project.tasks.withType(PublishToMavenRepository) { publishTask ->
		def oldArtifacts = publishTask.publication.artifacts.toArray()
		publishTask.publication.artifacts.clear()
		oldArtifacts.each({ artifact ->
			publishTask.publication.artifacts.artifact(
				source: artifact.file.getAbsolutePath().replaceAll(publishTask.publication.version, project.version),
				classifier: artifact.classifier,
				extension: artifact.extension
			)
		})
		if (isRelease) {
			publishTask.repository.url repositoryReleases
		} else {
			publishTask.repository.url repositorySnapshots
		}
		publishTask.publication.version = project.version
	}
	project.tasks.withType(GenerateMavenPom).each { generateMavenPomTask ->
		generateMavenPomTask.pom.getProjectIdentity().version = project.version
	}
}

// Groovy method declaration

def getDate() {
	def date = new Date()
	def formattedDate = date.format('yyyyMMdd')
	return formattedDate
}

// Detailled settings (dependencies, tasks, task configuration, ...)

repositories {
	mavenCentral()
}

buildscript {
	apply from: 'http://www.krismer.de/files/checkstyle.gradle'

	repositories {
		jcenter()
		maven { url 'http://dl.bintray.com/content/aalmiray/asciidoctor'}
	}

	dependencies {
		classpath 'org.gradle.api.plugins:gradle-vagrant-plugin:0.5'
		classpath 'org.asciidoctor:asciidoctor-gradle-plugin:0.7.0'
	}
}

dependencies {
	compile group: 'commons-dbutils', name: 'commons-dbutils', version:'1.2'
	compile group: 'commons-io', name: 'commons-io', version:'2.4'
	compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.3.0'
	compile group: 'com.jolbox', name: 'bonecp', version: '0.8.0.RELEASE'
	compile group: 'com.tngtech.java', name: 'config-builder', version: '1.2'
	compile group: 'org.postgresql', name: 'postgresql', version:'9.2-1004-jdbc41'

	runtime 'org.slf4j:jcl-over-slf4j:1.7.5'
	runtime 'ch.qos.logback:logback-classic:1.0.13'

	testCompile 'org.testng:testng:6+'
//	testCompile 'org.apache.jmeter:ApacheJMeter:2.+'
}

tasks.withType(JavaCompile) {
	// adds support for compiler warnings generation
	options.compilerArgs << '-Xlint:all,-processing'
}

tasks.withType(JavaCompile) {
	// workaround for http://issues.gradle.org/browse/GRADLE-1230
	doFirst { println '' }
}

asciidoctor {
	backend = 'html5'
	sourceDir = file('doc')
	outputDir = file("$buildDir/docs/asciidoctor")
}

eclipse {
	classpath {
		file {
			// See: http://forums.gradle.org/gradle/topics/eclipse_wtp_deploys_testcode_to_server_example_provided
			// Sets output folders for compiled classes and resources... otherwise test classes/resources would be deployed to wtp server
			whenMerged { cp ->
				cp.entries.findAll { it.path.startsWith('src/main/') }*.output = 'bin'
				cp.entries.findAll { it.path.startsWith('src/test/') }*.output = 'bin-test'
				// Sets JavaSE as jdk version used (instead of version directly)
		        cp.entries.findAll { it.path.contains('JRE_CONTAINER') }.each {
		            it.path += '/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-' + sourceCompatibility
		        }
			}
		}
	}

	project {
		buildCommand 'net.sf.eclipsecs.core.CheckstyleBuilder'

		natures = [
			'net.sf.eclipsecs.core.CheckstyleNature',
			'org.springsource.ide.eclipse.gradle.core.nature',
			'org.eclipse.jdt.core.javanature'
		]

		file {
			withXml { xmlProvider ->
				Node project = xmlProvider.asNode()
				Node filteredResources = project.appendNode('filteredResources');

				Node filterGradle = filteredResources.appendNode('filter')
				filterGradle.appendNode('id', 1392635165065)
				filterGradle.appendNode('name', '')
				filterGradle.appendNode('type', 30)
				Node matcherGradle = filterGradle.appendNode('matcher')
				matcherGradle.appendNode('id', 'org.eclipse.ui.ide.multiFilter')
				matcherGradle.appendNode('arguments', '1.0-name-matches-false-false-.gradle')

				Node filterVagrant = filteredResources.appendNode('filter')
				filterVagrant.appendNode('id', 1392635165131)
				filterVagrant.appendNode('name', '')
				filterVagrant.appendNode('type', 30)
				Node matcherVagrant = filterVagrant.appendNode('matcher')
				matcherVagrant.appendNode('id', 'org.eclipse.ui.ide.multiFilter')
				matcherVagrant.appendNode('arguments', '1.0-name-matches-false-false-.vagrant')
			}
		}
	}
}

findbugs {
	effort = 'max'
	ignoreFailures = true
	toolVersion = '2.0.3'
}

jar {
	description = 'Builds a jar file (without dependencies)'
	classifier = 'dynamic'
}

publishing {
	publications {
		mavenJava(MavenPublication) {
			from components.java

			artifact javadocJar
			artifact sourcesJar
			artifact staticJar
		}
	}

	repositories {
		maven {
			credentials {
				username repositoryUsername
				password repositoryPassword
			}
			// url is configured in versioning part
		}
	}
}

test {
	useTestNG {
		useDefaultListeners = true
	}

	ignoreFailures = true
	minHeapSize = '128m'
	maxHeapSize = '1024m'
}

test.doFirst {
	// TestNG XMLReporter does not create reportDir (but would fail without it)
	if (!project.testReportDir.isDirectory()) {
		project.testReportDir.mkdirs()
	}
}

vagrant {
	provider = 'virtualbox'
}

vagrantDestroy.doFirst {
	if (!vagrantDir.isDirectory()) {
		throw new StopExecutionException()
	}
}

// Custom task definitions

task cleanAfterDaily(type: Delete) {
	delete "$buildDir/dependency-cache"
	delete "$buildDir/tmp"
	delete ".gradle"
}

task cleanNodeModules(type: Delete) {
	delete files('node_modules')
}

task cleanTestResults(type: Delete) {
	// We only need the test reports... not the binary results
	delete project.testResultsDir
}

task javadocJar(type: Jar, dependsOn: javadoc) {
	description = 'Builds a jar file including javadoc'
	from javadoc.destinationDir

	classifier 'javadoc'
}

task processResourcesTest << {
	if (!isRelease) {
		// we add a config-test.xml for SNAPSHOT releases (so that the cfg.tablePrefix is defined)
		// otherwise testing and stable version would collide on testsystem
		// and testing in jenkins would search for geoserver/postgis on jenkins-server
		// (since localhost is default value in config-files -> needed for development)
		copy {
			from('src/test/resources') {
				include '*-test.xml'
			}
			into "${project.buildDir}/resources/main"
		}
	}
}

task sourcesJar(type: Jar, dependsOn: classes) {
	description = 'Builds a jar file including sources'
	from sourceSets.main.allSource

	classifier 'sources'
}

task staticJar(type: Jar) {
	description = 'Builds a jar file including all libraries'
	from sourceSets.main.output
	from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }

	classifier = 'static'
}

task testSimple(type: Test, dependsOn: testClasses) {
	useTestNG()
	jvmArgs '-Xmx4096m'

	include '**/RunSimple*'
}

task vagrantExport(type: Zip) {
	description = 'Builds an archive file that contains the files, needed to create the vagrant box'

	from 'etc/vagrant'

	appendix = ''
	baseName = 'vagrantbox'
	classifier = ''
	version = getDate()

	filter(FixCrLfFilter)
	filter(ReplaceTokens, tokens: [db_username: 'myUser', db_password: 'myPassword'])
}

task vagrantPrepare << {
	description = 'Prepares the vagrant environment (creates directory, copies Vagrantfile, ...)'

	if (!vagrantDir.isDirectory()) {
		println "Creating directory $vagrantDir and copying content"
		vagrantDir.mkdirs()

		sync {
			from files('etc/vagrant')
			into vagrantDir

			filter(FixCrLfFilter)
			filter(ReplaceTokens, tokens: [db_username: 'niko', db_password: 'secretPhdPassword#2014!'])
		}
	}
}

// CI tasks

task jarAll(dependsOn: [jar, javadocJar, sourcesJar, staticJar])
task buildAll(dependsOn: [jarAll, build])
task daily(dependsOn: [clean, asciidoctor, check, javadoc, jarAll])
task release

// task dependencies

tasks.cleanAfterDaily.dependsOn cleanNodeModules
tasks.daily.finalizedBy cleanAfterDaily
tasks.daily.mustRunAfter clean
tasks.processResources.finalizedBy processResourcesTest
tasks.test.finalizedBy cleanTestResults
tasks.vagrantUp.dependsOn vagrantPrepare