import org.gradle.api.Project
import org.gradle.api.DefaultTask
import org.gradle.api.Plugin
import org.gradle.api.tasks.TaskAction
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.credentials.HttpHeaderCredentials
import org.gradle.authentication.http.HttpHeaderAuthentication

class PublishJarsSettings {
  String gitlabUri = "https://gitlab.catalyst.net.nz/api/v4/projects/549/packages/maven"
  String groupId = 'nz.org.riskscape'
  String artifactId
  String authType
  String authToken
}

/**
 * Task for checking whether the auth is set or not, failing the build if it isn't
 */
class CheckGitlabCredsTask extends DefaultTask {

  @TaskAction
  def warnIfMissing() {
    def settings = project.extensions.publishJars

    if (!settings.authToken) {
      throw new RuntimeException("No authToken is set (not set via settings or RS_GITLAB_DEPLOY_TOKEN) can not publish jars")
    } else {
      logger.info("Using {} auth type against {}", settings.authType, settings.gitlabUri)
    }
  }
}

/**
 * Plugin for projects that want to publish their Jars. Makes it easy to install them in
 * in to either your local maven site (~/.m2/repo) or to GitLab's built in repo (good for
 * Sharing between CI jobs)
 */
class PublishJarsPlugin implements Plugin<Project> {

  void apply(Project project) {
    project.apply plugin: 'maven-publish'
    project.apply plugin: 'java-library'

    def settings = project.extensions.create('publishJars', PublishJarsSettings)

    // we have to wait to do our monkeying around only once the settings have been
    // evaluated - there might be a more fine grained hook, but this works for now
    project.afterEvaluate {

      project.java {
	withSourcesJar()
      }

      project.publishing {
	publications {
	  // describe the thing we're publishing
	  def publication = maven(MavenPublication)
	  setupMavenPublication(project, settings, publication)
	}

	// define some locations we can publish
	repositories {

	  // for local dev - you can point plugin projects at .m2 and get
	  // riskscape engine deps from there
	  mavenLocal()

	  // NB name has to be set within the closure
	  def gitlabRepo = maven {
	    name "GitLab"
	  }
	  // do the detailed setup
	  setupGitlabRepo(project, settings, gitlabRepo)
	}
      }

      // get a warning spat out if no creds present
      project.tasks.register('publishWarnOnMissingToken', CheckGitlabCredsTask)
      project.tasks.find { it.name == 'publishMavenPublicationToGitLabRepository' }.dependsOn('publishWarnOnMissingToken')
    }


  }

  void setupMavenPublication(project, settings, publication) {
    publication.groupId = settings.groupId
    publication.artifactId = settings.artifactId
    publication.version = project.project.property('riskscapeVersion')

    // replace dev with SNAPSHOT for jar publishing purposes - it's speshul
    if (publication.version.endsWith('-dev')) {
      publication.version = publication.version.replace('-dev', '') + '-SNAPSHOT'
    }

    publication.from project.components.java
  }

  void setupGitlabRepo(Project project, settings, gitlabRepo) {
    // here we detect what type of auth we're going to use - gitlab ci will export
    // a CI_JOB_TOKEN we can use, if you're a local dev and you want to publish
    // something you'll need to export GITLAB_PRIVATE_TOKEN
    //
    // NB this needs to fail silently *until* the point you try to publish jars
    // check for a ci token first, fall back to private token

    if (!settings.authToken) {
      settings.authToken = System.getenv('RS_GITLAB_DEPLOY_TOKEN')
    }

    if (!settings.authType) {
      settings.authType = System.getenv().getOrDefault('RS_GITLAB_DEPLOY_TOKEN_TYPE', 'Deploy-Token')
    }

    // this will allow publishing to gitlab, so that other projects in CI can
    // fetch dependencies
    // We can publish the jars above to just gitlab via with
    // ./gradlew publishMavenPublicationToGitLabRepository
    // what a mouthful!
    gitlabRepo.url settings.gitlabUri

    gitlabRepo.credentials(HttpHeaderCredentials) {
      name = settings.authType
      value = settings.authToken
    }

    gitlabRepo.authentication {
      header(HttpHeaderAuthentication)
    }
  }
}
