project.ext {
    springVersion = "3.2.2.RELEASE"
    grailsVersion = "2.3.0.BUILD-SNAPSHOT"
    slf4jVersion = "1.7.2"
    groovyVersion = System.getProperty('groovyVersion') ?: '2.1.2'
}

def groovyMajorVersion = groovyVersion[0..2]
def spockDependency = "org.spockframework:spock-core:0.7-groovy-2.0"

def groovyProjects() {
    subprojects.findAll { project -> isGroovyProject(project) }
}

def isGroovyProject(project) {
    def isGrailsPlugin = project.name.contains("grails-plugins")
    def isDocumentation = project.name.contains("documentation")
    !isGrailsPlugin && !isDocumentation
}

configurations {
   all*.exclude group: "commons-logging"
}

apply plugin: 'idea'
apply plugin: 'project-report'


ext {
    isCiBuild = project.hasProperty("isCiBuild")
}
allprojects {
    repositories {
        if(!isCiBuild) {
            mavenLocal()
        }
        mavenCentral()
        maven { url "http://repo.grails.org/grails/core" }
    }

    configurations {
        all {
            resolutionStrategy {
                def cacheHours = isCiBuild ? 1 : 24
                cacheDynamicVersionsFor cacheHours, 'hours'
                cacheChangingModulesFor cacheHours, 'hours'
            }
        }
    }
}

task wrapper(type: Wrapper) {
    gradleVersion = '1.5'
}

subprojects {
    ext {
//        releaseType = "RELEASE"
       releaseType = "BUILD-SNAPSHOT"
        //releaseType = "RC3"
        isCiBuild = project.hasProperty("isCiBuild")
        isBuildSnapshot = releaseType == "BUILD-SNAPSHOT"
    }

    version = "2.0.0.${releaseType}"
    group = "org.grails"


    def isStandardGroovyMavenProject = isGroovyProject(project)

    if (isStandardGroovyMavenProject) {
        apply plugin: 'groovy'
        apply plugin: 'eclipse'
        apply plugin: 'maven'
        apply plugin: 'idea'
        apply plugin: 'signing'
        sourceCompatibility = "1.6"
        targetCompatibility = "1.6"

/*        apply from: "file:${rootDir}/clover.gradle"*/

        install.doLast {
            def gradleArtifactCache = new File(gradle.gradleUserHomeDir, "cache")
            configurations.archives.artifacts.findAll { it.type == "jar" && !it.classifier }.each { artifact ->

                // Gradle's cache layout is internal and may change in future versions, this is written for gradle 1.0-milestone-3
                def artifactInCache = file("${gradleArtifactCache}/${project.group}/${project.name}/jars/${project.name}-${version}.jar")
                if (artifactInCache.parentFile.mkdirs()) {
                    artifactInCache.withOutputStream { destination ->  artifact.file.withInputStream { destination << it } }
                }
            }
        }
    }

    def isGormDatasource = project.name.startsWith("grails-datastore-gorm-") && !project.name.endsWith("tck") && !project.name.endsWith("plugin-support")
    def isDocumentationProject = project.name.startsWith("grails-documentation")

    dependencies {
        if (isStandardGroovyMavenProject) {
            groovy group: 'org.codehaus.groovy', name: 'groovy-all', version: groovyVersion

            testCompile 'junit:junit:4.8.2'
            testCompile (spockDependency) {
                transitive = false
            }
        }

        if (project.name == "grails-datastore-gorm-tck") {
            compile spockDependency
        }
    }

    if (isDocumentationProject) {
        configurations {
            documentation
        }
        dependencies {
            documentation group: 'org.grails', name: 'grails-docs', version: '2.0.0'
            project(":grails-datastore-core")
            documentation "org.slf4j:jcl-over-slf4j:$slf4jVersion"
            documentation "org.slf4j:slf4j-api:$slf4jVersion"
            documentation "org.slf4j:slf4j-simple:$slf4jVersion"
        }
        task docs << {
            ant.taskdef (name: 'docs', classname : 'grails.doc.ant.DocPublisherTask') {
                classpath {
                    configurations.documentation.resolve().each { f ->
                        pathelement(location:f)
                    }
                }

            }
            ant.docs(src:"src/docs", dest:destinationDir, properties:"src/docs/doc.properties")
        }
        docs.ext.destinationDir = "${buildDir}/docs"


        task clean << {
            ant.delete(dir:buildDir)
        }
    }

    if (isGormDatasource) {
        dependencies {
            testCompile project(":grails-datastore-gorm-tck")
        }

        // We need to test against the TCK. Gradle cannot find/run tests from jars
        // without a lot of plumbing, so here we copy the class files from the TCK
        // project into this project's test classes dir so Gradle can find the test
        // classes and run them. See grails.gorm.tests.GormDatastoreSpec for on the TCK.

        // helper, used below.
        def toBaseClassRelativePathWithoutExtension = { String base, String classFile ->
            if (classFile.startsWith(base)) {
                def sansClass = classFile[0 .. classFile.size() - ".class".size() - 1]
                def dollarIndex = sansClass.indexOf('$')
                def baseClass = dollarIndex > 0 ? sansClass[0..dollarIndex - 1] : sansClass
                def relative = baseClass - base - '/'
                relative
            }
            else {
                null
            }
        }
        
        test {
            maxHeapSize = '1024m'
        }        
        test.doFirst {
            def tckClassesDir = project(":grails-datastore-gorm-tck").sourceSets.main.output.classesDir
            def thisProjectsTests = // surely there is a less hardcoded way to do this
            copy {
                from tckClassesDir
                into sourceSets.test.output.classesDir
                include "**/*.class"
                exclude { details ->
                    // Do not copy across any TCK class (or nested classes of that class)
                    // If there is a corresponding source file in the particular modules
                    // test source tree. Allows a module to override a test/helper.

                    def candidatePath = details.file.absolutePath
                    def relativePath = toBaseClassRelativePathWithoutExtension(tckClassesDir.absolutePath, candidatePath)

                    if (relativePath == null) {
                        throw new IllegalStateException("$candidatePath does not appear to be in the TCK")
                    }

                    project.file("src/test/groovy/${relativePath}.groovy").exists()
                }
            }
        }
    }

    if (isStandardGroovyMavenProject) {

        task sourcesJar(type: Jar, dependsOn:classes) {
            classifier = 'sources'
            from sourceSets.main.allSource
        }

        task javadocJar(type: Jar, dependsOn:javadoc) {
            classifier = 'javadoc'
            from javadoc.destinationDir
        }

        artifacts {
            archives jar
            archives sourcesJar
            archives javadocJar
        }

        signing {
            sign configurations.archives
            required { !isBuildSnapshot && gradle.taskGraph.hasTask(uploadArchives) }
        }

        configure(install.repositories.mavenInstaller) {
            pom.whenConfigured { pom ->
                def dependency = pom.dependencies.find { dep -> dep.artifactId == 'slf4j-simple' }
                dependency?.optional = true
            }
            pom.project {
                licenses {
                    license {
                        name 'The Apache Software License, Version 2.0'
                        url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
                        distribution 'http://github.com/SpringSource/grails-data-mapping/'
                    }
                }
            }
        }

        uploadArchives {
            description = "Does a maven deploy of archives artifacts"

            // add a configuration with a classpath that includes our s3 maven deployer
            configurations { deployerJars }
            dependencies {
                deployerJars "org.springframework.build.aws:org.springframework.build.aws.maven:3.0.0.RELEASE"
            }

            repositories.mavenDeployer {
                beforeDeployment { MavenDeployment deployment ->
                    signing.signPom(deployment)
                }

                repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") {
                    authentication(userName: project.hasProperty("sonatypeUsername") ? project.sonatypeUsername : null,
                            password: project.hasProperty("sonatypePassword") ?  project.sonatypePassword : null)
                }
                snapshotRepository(url: "http://repo.grails.org/grails/libs-snapshots-local") {
                    authentication(userName: project.hasProperty("artifactoryPublishUsername") ? project.artifactoryPublishUsername : null,
                            password: project.hasProperty("artifactoryPublishPassword") ?  project.artifactoryPublishPassword : null)
                }

                pom.project {
                    name 'Grails GORM'
                    packaging 'jar'
                    description 'GORM - Grails Data Access Framework'
                    delegate.url 'http://grails.org/'

                    licenses {
                        license {
                            name 'The Apache Software License, Version 2.0'
                            url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
                            distribution 'repo'
                        }
                    }

                    scm {
                        delegate.url 'scm:git@github.com:SpringSource/grails-data-mapping.git'
                        connection 'scm:git@github.com:SpringSource/grails-data-mapping.git'
                        developerConnection 'scm:git@github.com:SpringSource/grails-data-mapping.git'
                    }

                    licenses {
                        license {
                            name 'The Apache Software License, Version 2.0'
                            delegate.url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
                            distribution 'repo'
                        }
                    }

                    developers {
                        developer {
                            id 'graemerocher'
                            name 'Graeme Rocher'
                        }
                        developer {
                            id 'jeffscottbrown'
                            name 'Jeff Brown'
                        }
                        developer {
                            id 'burtbeckwith'
                            name 'Burt Beckwith'
                        }
                    }
                }
            }
        }
    }
}

configurations {
    build
}

repositories {
    mavenCentral()
}

dependencies {
    build "com.cenqua.clover:clover:3.0.2"
    build "org.apache.ant:ant-junit:1.8.1"
    build "org.apache.ant:ant-nodeps:1.8.1"
}

task allDocs(dependsOn: getTasksByName("docs", true)) << {
    def docTasks = getTasksByName("docs", true)
    def groovydocTasks = getTasksByName("groovydoc", true)
    allDocsDir = "$buildDir/docs"
    mkdir allDocsDir
    def stores = []
    for(task in docTasks) {
        def dir = task.destinationDir
        def projectName = task.project.name
        if (projectName.endsWith("core")) {
            mkdir "$allDocsDir/manual"
            fileTree { from dir }.copy { into "$allDocsDir/manual" }
            def groovydocTask = groovydocTasks.find { it.project.name.endsWith "core" }
            if (groovydocTask != null) {
                mkdir "$allDocsDir/api"
                groovydocTask.actions.each { it.execute(groovydocTask) }

                fileTree { from groovydocTask.destinationDir }.copy { into "$allDocsDir/api"}
            }
        }
        else {
            def storeName = projectName["grails-documentation-".size()..-1]
            stores << storeName
            def docsDir = "$allDocsDir/$storeName"
            mkdir docsDir
            def groovydocTask = groovydocTasks.find { it.project.name == "grails-datastore-$storeName" }
            if (groovydocTask == null) groovydocTask = groovydocTasks.find { it.project.name == "grails-datastore-gorm-$storeName" }
            if (groovydocTask != null) {
                mkdir "$docsDir/api"
                groovydocTask.actions.each { it.execute(groovydocTask) }
                fileTree { from groovydocTask.destinationDir }.copy { into "$docsDir/api"}
            }
            mkdir "$docsDir/manual"
            fileTree { from dir }.copy { into "$docsDir/manual" }
        }

        def engine = new groovy.text.SimpleTemplateEngine()
        def binding = [
            datastores:stores.collect { "<li><a href=\"$it/index.html\">GORM for ${it[0].toUpperCase()}${it[1..-1]}</a></li>" }.join(System.getProperty("line.separator"))
        ]
        def template = engine.createTemplate(new File("src/docs/resources/core.template")).make(binding)
        new File("$allDocsDir/index.html").text = template.toString()

        for(store in stores) {
            def index = "$allDocsDir/$store/index.html"
            def storeName = "${store[0].toUpperCase()}${store[1..-1]}".toString()
            binding = [
                datastore:storeName
            ]
            template = engine.createTemplate(new File("src/docs/resources/datastore.template")).make( binding )
            new File(index).text = template.toString()
        }
    }
}

task test(dependsOn: getTasksByName("test", true)) << {
    def reportsDir = "${buildDir}/reports"

    // Aggregate the test results
    ant.taskdef(
        name: 'junitreport2',
        classname: "org.apache.tools.ant.taskdefs.optional.junit.XMLResultAggregator",
        classpath: configurations.build.asPath
    )

    def testReportsDir = new File("${reportsDir}/tests")
    if (testReportsDir.exists()) {
        testReportsDir.deleteDir()
    }
    testReportsDir.mkdirs()

    ant.junitreport2(todir: testReportsDir) {
        subprojects.each {
            def testResultsDir = "${it.buildDir}/test-results"
            if (new File(testResultsDir).exists()) {
                fileset(dir: testResultsDir) {
                    include(name: "TEST-*.xml")
                }
            }
        }
        report(todir: testReportsDir)
    }

    // Aggregate the coverage results
    if (project.hasProperty("withClover")) {
        def db = "clover/clover.db"
        def mergedDb = "${buildDir}/${db}"
        def cloverReportsDir = "${reportsDir}/clover"
        ant.taskdef(resource: "cloverlib.xml", classpath: configurations.build.asPath)
        ant."clover-merge"(initstring: mergedDb) {
            subprojects.each {
                def projectCloverDb = "${it.buildDir}/${db}"
                if (new File(projectCloverDb).exists()) {
                    cloverdb(initstring: projectCloverDb)
                }
            }
        }
        ant."clover-report"(initstring: mergedDb) {
            current(outfile:"${cloverReportsDir}/clover.xml")
        }
        ant."clover-html-report"(initstring: mergedDb, outdir:"${cloverReportsDir}/html")
    }
}