import eclipsebuild.BuildshipConfig
import eclipsebuild.Config
import eclipsebuild.Constants
import eclipsebuild.LogOutputStream

plugins {
    id 'com.gradle.build-scan' version '1.8'
}

apply plugin: eclipsebuild.BuildDefinitionPlugin

ext.toolingApiBundleVersion = getBundleVersion(toolingApiVersion)

// define version mapping for the 3rd-party dependencies that are not specific to a particular Eclipse version
def eclipseVersionAgnosticDependencies = [
    'org.gradle.toolingapi'             : toolingApiBundleVersion,
    'org.slf4j.api'                     : '1.7.2',
    'org.slf4j.simple'                  : '1.7.2',
    'com.google.guava'                  : '21.0.0',
    'com.google.gson'                   : '2.7.0',
    'org.apache.log4j'                  : '1.2.15',
    'org.eclipse.swtbot.eclipse.finder' : '2.2.1',
    'org.eclipse.swtbot.junit4_x'       : '2.2.1',
]

// target platform definition for all major Eclipse releases between version 4.5 and 4.7
// the default version is 49 which can be overridden through -Peclipse.version=<version>
// also the target platforms contain 1) the Eclipse SDK 2) the latest junit 3) SWTBot 2.2.1
eclipseBuild {
    defaultEclipseVersion = '49'

    final def swtPluginId = "org.eclipse.swt.${ECLIPSE_WS}.${ECLIPSE_OS}.${ECLIPSE_ARCH}"

    targetPlatform {
        eclipseVersion = '45'
        targetDefinition = file('tooling-e45.target')
        versionMapping = [
            'org.eclipse.core.expressions'          : '3.5.0',
            'org.eclipse.core.runtime'              : '3.11.0',
            'org.eclipse.core.resources'            : '3.10.0',
            'org.eclipse.core.variables'            : '3.2.800',
            'org.eclipse.core.filesystem'           : '1.5.0',
            'org.eclipse.core.net'                  : '1.2.300',
            'org.eclipse.jdt.core'                  : '3.11.0',
            'org.eclipse.jdt.junit.core'            : '3.7.400',
            'org.eclipse.jdt.launching'             : '3.8.0',
            'org.eclipse.debug.core'                : '3.10.0',
            'org.eclipse.core.databinding'          : '1.5.0',
            'org.eclipse.core.databinding.beans'    : '1.3.0',
            'org.eclipse.core.databinding.property' : '1.5.0',
            'org.eclipse.help'                      : '3.6.0',
            'org.eclipse.ui'                        : '3.107.0',
            'org.eclipse.ui.ide'                    : '3.11.0',
            'org.eclipse.ui.console'                : '3.6.0',
            'org.eclipse.ui.editors'                : '3.9.0',
            'org.eclipse.ui.views'                  : '3.8.0',
            'org.eclipse.debug.ui'                  : '3.11.0',
            'org.eclipse.jdt.ui'                    : '3.11.0',
            'org.eclipse.jface.databinding'         : '1.7.0',
            'org.eclipse.jface.text'                : '3.10.0',
            'com.ibm.icu'                           : '54.1.1',
            'org.junit'                             : '4.11.0',
            "$swtPluginId"                          : "3.104.0"
        ] + eclipseVersionAgnosticDependencies
    }

    targetPlatform {
        eclipseVersion = '46'
        targetDefinition = file('tooling-e46.target')
        // TODO define version mapping similarly as above; it makes dependency resolution faster
        versionMapping = eclipseVersionAgnosticDependencies
    }

    targetPlatform {
        eclipseVersion = '47'
        targetDefinition = file('tooling-e47.target')
        // TODO define version mapping similarly as above; it makes dependency resolution faster
        versionMapping = eclipseVersionAgnosticDependencies
    }
    
    targetPlatform {
        eclipseVersion = '49'
        targetDefinition = file('tooling-e49.target')
        versionMapping = [
            "$swtPluginId"                          : '3.108.0',
            'com.ibm.icu'                           : '62.1.0',
            'org.eclipse.core.expressions'          : '3.6.200',
            'org.eclipse.core.filesystem'           : '1.7.200',
            'org.eclipse.core.net'                  : '1.3.300',
            'org.eclipse.core.resources'            : '3.13.100',
            'org.eclipse.core.runtime'              : '3.15.0',
            'org.eclipse.core.variables'            : '3.4.200',
            'org.eclipse.debug.core'                : '3.13.0',
            'org.eclipse.debug.ui'                  : '3.13.100',
            'org.eclipse.help'                      : '3.8.200',
            'org.eclipse.jdt.core'                  : '3.15.0',
            'org.eclipse.jdt.junit.core'            : '3.10.100',
            'org.eclipse.jdt.launching'             : '3.11.0',
            'org.eclipse.jdt.ui'                    : '3.15.0',
            'org.eclipse.jface.databinding'         : '1.8.300',
            'org.eclipse.jface.text'                : '3.14.0',
            'org.eclipse.ui'                        : '3.110.0',
            'org.eclipse.ui.console'                : '3.8.100',
            'org.eclipse.ui.editors'                : '3.11.200',
            'org.eclipse.ui.ide'                    : '3.14.100',
            'org.eclipse.ui.navigator'              : '3.7.200',
            'org.eclipse.ui.views'                  : '3.9.200',
            'org.eclipse.ui.workbench.texteditor'   : '3.11.100',
            'org.junit'                             : '4.12.0'
        ] + eclipseVersionAgnosticDependencies
    }

    targetPlatform {
        eclipseVersion = '410'
        targetDefinition = file('tooling-e410.target')
        versionMapping = [
            "$swtPluginId"                          : '3.108.100',
            'com.ibm.icu'                           : '62.1.0',
            'org.eclipse.core.expressions'          : '3.6.200',
            'org.eclipse.core.filesystem'           : '1.7.200',
            'org.eclipse.core.net'                  : '1.3.300',
            'org.eclipse.core.resources'            : '3.13.200',
            'org.eclipse.core.runtime'              : '3.15.100',
            'org.eclipse.core.variables'            : '3.4.200',
            'org.eclipse.debug.core'                : '3.13.100',
            'org.eclipse.debug.ui'                  : '3.13.200',
            'org.eclipse.help'                      : '3.8.200',
            'org.eclipse.jdt.core'                  : '3.16.0',
            'org.eclipse.jdt.junit.core'            : '3.10.200',
            'org.eclipse.jdt.launching'             : '3.11.100',
            'org.eclipse.jdt.ui'                    : '3.15.100',
            'org.eclipse.jface.databinding'         : '1.8.400',
            'org.eclipse.jface.text'                : '3.15.0',
            'org.eclipse.ui'                        : '3.110.0',
            'org.eclipse.ui.console'                : '3.8.200',
            'org.eclipse.ui.editors'                : '3.11.300',
            'org.eclipse.ui.ide'                    : '3.14.200',
            'org.eclipse.ui.navigator'              : '3.7.300',
            'org.eclipse.ui.views'                  : '3.9.200',
            'org.eclipse.ui.workbench.texteditor'   : '3.11.200',
            'org.junit'                             : '4.12.0'
        ] + eclipseVersionAgnosticDependencies
    }
}

// read the current version from an external file and add a timestamp suffix if requested by the caller
ext.baseVersion = file('version.txt').text.trim()
version = getVersion(baseVersion)

// ensure that the assembleTargetPlatform is executed when the gradle.properties file is changed
project.assembleTargetPlatform.inputs.file file('gradle.properties')

// delete the org.eclipse.core.runtime.compatibility.registry plugin from the target platform
// it causes classpath issues when the the Spock tests are running with Groovy 2.4; only
// contains files to provide 2.x compatibility hence it's safe to remove
project.assembleTargetPlatform.doLast {
    def config = Config.on(project)
    if (config.targetPlatform.eclipseVersion < '46') {
        def registryPluginId = 'org.eclipse.core.runtime.compatibility.registry'

        project.exec {
            // redirect the external process output to the logging
            standardOutput = new LogOutputStream(project.logger, LogLevel.INFO)
            errorOutput = new LogOutputStream(project.logger, LogLevel.INFO)

            commandLine(config.eclipseSdkExe.path,
                    '-application', 'org.eclipse.equinox.p2.director',
                    '-uninstallIU', registryPluginId,
                    '-tag', 'target-platform-2',
                    '-destination', config.nonMavenizedTargetPlatformDir.path,
                    '-profile', 'SDKProfile',
                    '-bundlepool', config.nonMavenizedTargetPlatformDir.path,
                    '-p2.os', Constants.os,
                    '-p2.ws', Constants.ws,
                    '-p2.arch', Constants.arch,
                    '-roaming',
                    '-nosplash')
        }

        def bundlesInfo = new File(config.nonMavenizedTargetPlatformDir, 'configuration/org.eclipse.equinox.simpleconfigurator/bundles.info')
        def updatedInfo = ''
        bundlesInfo.withReader { reader ->
            def line
            while (line = reader.readLine()) {
                if (!line.contains(registryPluginId)) {
                    updatedInfo += line + '\n'
                }
            }
        }
        bundlesInfo.text = updatedInfo
    }
}

subprojects {
    // set the calculated version on all projects in the hierarchy
    version = rootProject.version

    repositories {
    	maven {
            name = 'mavenized-target-platform'
            url "${eclipsebuild.Config.on(project).mavenizedTargetPlatformDir}"
        }
    	maven {
            name = 'gradle-remote'
            url gradleRemoteRepositoryUrl
        }
    }
}

tasks.withType(eclipsebuild.DownloadEclipseSdkTask) {
    def os = org.gradle.internal.os.OperatingSystem.current()
    def arch = System.getProperty("os.arch").contains("64") ? "64" : "32"
    if (os.windows) {
        downloadUrl = "http://builds.gradle.org:8000/eclipse/sdk/eclipse-sdk-4.4.2-windows-${arch}.zip"
    } else if (os.macOsX) {
        downloadUrl = "http://builds.gradle.org:8000/eclipse/sdk/eclipse-sdk-4.4.2-macosx-${arch}.tar.gz"
    } else if (os.linux) {
        downloadUrl = "http://builds.gradle.org:8000/eclipse/sdk/eclipse-sdk-4.4.2-linux-${arch}.tar.gz"
    }
}

String getVersion(def baseVersion) {
    def config = BuildshipConfig.on(project)

    // determine suffix for snapshot and milestone builds
    def suffix
    if (config.isRelease()) {
        suffix = ''
    } else if (config.isMilestone()) {
        suffix = '-m'
    } else if (config.isSnapshot()) {
        suffix = '-s'
    } else if (config.isDevelopment()) {
        suffix = '-d'
    } else {
        throw new IllegalStateException("BuildshipConfig must either be a release, milestone, snapshot or development.")
    }

    // use full timestamp on CI vs. date-only for local builds
    if (project.hasProperty('build.invoker') && project.property('build.invoker') == 'ci') {
        // note that for Eclipse plugin versions, the '-' and '.' character are invalid in front of the build id
        baseVersion + '.v' + new Date().format('yyyyMMdd-kkmm', TimeZone.getTimeZone('GMT')) + suffix
    } else {
        baseVersion + '.v' + new Date().format('yyyyMMdd', TimeZone.getTimeZone('GMT')) + suffix
    }
}

def getBundleVersion(String version) {
  def matcher = version =~ /(\d+)\.(\d+)(?:-.*|\.(\d+)(?:-.*)?)?/
  if (matcher.matches()) {
    def major = matcher.group(1)
    def minor = matcher.group(2)
    def service = matcher.group(3) ?: '0'
    return "$major.$minor.$service"
  } else {
    throw new IllegalArgumentException("Invalid bundle version: $version")
  }
}
