/*
 * Copyright Thoughtworks, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import com.thoughtworks.go.build.Architecture
import com.thoughtworks.go.build.InstallerMetadataTask
import com.thoughtworks.go.build.InstallerType
import org.apache.tools.ant.filters.ConcatFilter
import org.apache.tools.ant.filters.FixCrLfFilter

tasks.register('agentGenericZip', Zip) { Zip thisTask ->
  dependsOn configurations.agentBootstrapperJar
  configureGenericZip(thisTask, InstallerType.agent)

  from({ configurations.agentBootstrapperJar }) {
    rename "(.*)-${project.version}.(.*)", '$1.$2'
    into "lib"
  }

  from("go-agent/release/README-running-multiple-agents.md")

  finalizedBy "${thisTask.name}Metadata"
}

tasks.register('serverGenericZip', Zip) { Zip thisTask ->
  dependsOn configurations.serverJar
  configureGenericZip(thisTask, InstallerType.server)

  from({ configurations.serverJar }) {
    rename "(.*)-${project.version}.(.*)", 'go.jar'
    into "lib"
  }

  finalizedBy "${thisTask.name}Metadata"
}

['agent', 'server'].each { installerType ->
  def packageTaskName = "${installerType}GenericZip"
  tasks.register("${packageTaskName}Metadata", InstallerMetadataTask) {
    architecture = Architecture.all
    packageTask = project.tasks.named(packageTaskName)
    type = InstallerType."${installerType}"
  }
}

assemble.dependsOn(":installers:agentGenericZip", ":installers:serverGenericZip")

def configureGenericZip(Zip zipTask, InstallerType installerType) {
  zipTask.with {
    dependsOn extractDeltaPack

    destinationDirectory = project.base.distsDirectory.dir("zip")
    archiveBaseName = installerType.baseName

    into("${installerType.baseName}-${project.goVersions.goVersion}")

    from("${rootProject.projectDir}/LICENSE")

    from("${extractDeltaPack.destinationDir}/src/bin/App.sh.in") {
      filter({ String eachLine ->
        eachLine = eachLine
          .replaceAll('@app.name@', installerType.baseName)
          .replaceAll('@app.long.name@', installerType.baseName)
          .replaceAll('@app.description@', installerType.baseName)

        if (eachLine == 'WRAPPER_CMD="./wrapper"') {
          eachLine = 'WRAPPER_CMD="../wrapper/wrapper"'
        }

        if (eachLine == 'WRAPPER_CONF="../conf/wrapper.conf"') {
          eachLine = 'WRAPPER_CONF="../wrapper-config/wrapper.conf"'
        }

        if (eachLine == 'PIDDIR="."') {
          eachLine = 'PIDDIR="../run"'
        }

        if (eachLine =~ /^#PASS_THROUGH=/ && installerType.allowPassthrough) {
          eachLine = 'PASS_THROUGH=true'
        }

        return eachLine
      })

      filter(FixCrLfFilter.class, eol: FixCrLfFilter.CrLf.newInstance("unix"))
      rename 'App.sh.in', installerType.baseName
      into "bin"
      filePermissions {
        unix(0755)
      }
    }

    from("${extractDeltaPack.destinationDir}/src/bin") {
      // See https://wrapper.tanukisoftware.com/doc/english/launch-win.html#dedicated-setup
      include 'App.bat.in' // to run app as a console app
      rename 'App.bat.in', "${installerType.baseName}.bat"

      include 'InstallApp-NT.bat.in' // to install GoCD as a service
      rename 'InstallApp-NT.bat.in', "install-${installerType.baseName}-service.bat"

      include 'UninstallApp-NT.bat.in' // to remove GoCD as a service
      rename 'UninstallApp-NT.bat.in', "uninstall-${installerType.baseName}-service.bat"

      include 'StartApp-NT.bat.in' // to start the GoCD service
      rename 'StartApp-NT.bat.in', "start-${installerType.baseName}-service.bat"

      include 'StopApp-NT.bat.in' // to stop the GoCD service
      rename 'StopApp-NT.bat.in', "stop-${installerType.baseName}-service.bat"

      include 'PauseApp-NT.bat.in' // to pause the GoCD service
      rename 'PauseApp-NT.bat.in', "pause-${installerType.baseName}-service.bat"

      include 'ResumeApp-NT.bat.in' // to resume the GoCD service
      rename 'ResumeApp-NT.bat.in', "resume-${installerType.baseName}-service.bat"

      include 'QueryApp-NT.bat.in' // to get the status of the GoCD service
      rename 'QueryApp-NT.bat.in', "query-${installerType.baseName}-service.bat"

      into "bin"

      filter({ String eachLine ->
        if (eachLine == 'set _WRAPPER_DIR=') {
          eachLine = 'set _WRAPPER_DIR="../wrapper"'
        }

        if (eachLine == 'set _WRAPPER_CONF_DEFAULT="../conf/%_WRAPPER_BASE%.conf"') {
          eachLine = 'set _WRAPPER_CONF_DEFAULT="../wrapper-config/%_WRAPPER_BASE%.conf"'
        }

        if (eachLine =~ /^rem set _PASS_THROUGH=/ && installerType.allowPassthrough) {
          eachLine = 'set _PASS_THROUGH=true'
        }

        return eachLine
      })

      filter(FixCrLfFilter.class, eol: FixCrLfFilter.CrLf.newInstance("dos"))
    }

    from("${extractDeltaPack.destinationDir}/src/conf/wrapper.conf.in") {
      filter({ String eachLine ->
        eachLine = eachLine
          .replaceAll('@app.name@', installerType.baseName)
          .replaceAll('@app.long.name@', installerType.baseName)
          .replaceAll('@app.description@', installerType.baseName)

        if (eachLine == 'wrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperSimpleApp') {
          eachLine = 'wrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperJarApp'
        }

        if (eachLine == '@encoding=UTF-8') {
          def newLines = [
            '@encoding=UTF-8',
            'wrapper.working.dir=..',
            'wrapper.console_input=DISABLED',
            'wrapper.console.flush=TRUE'
          ]

          installerType.additionalEnvVars.forEach { k, v ->
            newLines.add("set.default.${k}=${v}")
          }

          eachLine = newLines.join('\n')
        }

        if (eachLine == 'wrapper.java.additional.1=' && !installerType.jvmArgs.isEmpty()) {
          def newLines = []

          installerType.jvmArgs.eachWithIndex { String eachArg, int index ->
            newLines << "wrapper.java.additional.${index + 1}=${eachArg}"
          }

          eachLine = newLines.join('\n')
        }

        if (eachLine == 'wrapper.jarfile=../lib/wrapper.jar') {
          eachLine = "wrapper.jarfile=wrapper/wrapper.jar"
        }

        if (eachLine == '#wrapper.java.classpath.1=') {
          eachLine = "wrapper.java.classpath.1=lib/${installerType.jarFileName}"
        }

        if (eachLine == 'wrapper.java.library.path.1=../lib') {
          eachLine = 'wrapper.java.library.path.1=wrapper'
        }

        if (eachLine == 'wrapper.app.parameter.1=<YourMainClass>') {
          eachLine = "wrapper.app.parameter.1=lib/${installerType.jarFileName}"
        }

        if (eachLine == 'wrapper.logfile=../logs/wrapper.log') {
          eachLine = "wrapper.logfile=logs/${installerType.logFileName}"
        }

        return eachLine
      })

      filter(ConcatFilter, append: file("include/wrapper-license-relative-path-${installerType.baseName}.conf"))
      filter(ConcatFilter, append: file("include/additional-properties.conf"))
      filter(FixCrLfFilter, eol: FixCrLfFilter.CrLf.newInstance("unix"))

      into 'wrapper-config'
      rename 'wrapper.conf.in', 'wrapper.conf'
    }

    zipTask.inputs.file("include/wrapper-license-relative-path-${installerType.baseName}.conf")
    zipTask.inputs.file("include/additional-properties.conf")

    // the actual default config file
    from("include/wrapper-properties-${installerType.baseName}.conf") {
      into 'wrapper-config'
      rename ".*", "wrapper-properties.conf"
      filter(ConcatFilter, append: file("include/wrapper-properties.${installerType.baseName}.conf.example"))
    }

    zipTask.inputs.file("include/wrapper-properties.${installerType.baseName}.conf.example")

    from("${extractDeltaPack.destinationDir}/bin") {
      include 'wrapper-*'
      into "wrapper"
    }

    from("${extractDeltaPack.destinationDir}/lib") {
      into "wrapper"
      include 'libwrapper-*'
      include 'wrapper.jar'
      include 'wrapper-*.dll'
    }

    from('empty-ignore-file') {
      into "logs"
      rename ".*", ".ignore"
    }

    from('empty-ignore-file') {
      into "run"
      rename ".*", ".ignore"
    }
  }
}
