import groovy.transform.Field

@Field ECR_REGISTRY = '086679231553'
@Field ECR_REGION = 'us-east-1'
@Field DOCKER_IMAGE = "${ECR_REGISTRY}.dkr.ecr.${ECR_REGION}.amazonaws.com/chef-workstation:latest"

def call(Map args = [:]) {
  def mainBranch = args.mainBranch ?: 'master'
  if (env.BRANCH_NAME == mainBranch) {
    // Wipe the workspace so we are building completely clean
    deleteDir()
    checkout scm

    withEcr(registries: [[accountId: ECR_REGISTRY, region: ECR_REGION]]) {
      withSecrets(awsAccountId: '086679231553', awsRole: 'shared-chef-workstation-deploy-role', secrets: [
          [id: 'shared/chef-workstation/CLIENT_KEY', environmentVariable: 'CLIENT_KEY'],
      ]) {
        println "${env.BRANCH_NAME} detected - cookbook upload started."
        def jobBaseName = JOB_NAME.tokenize('/') as String[]
        ansiColor('xterm') {
          uploadCookbook(jobBaseName[1])
        }
        println 'Cookbook upload finished.'
      }
    }
  }
}

def dockerRun(Map args) {
  sh(returnStatus: args.returnStatus, returnStdout: args.returnStdout, script: "docker run --rm -v \"\$(pwd):/repository\" -w /repository -e CLIENT_KEY ${DOCKER_IMAGE} ${args.script}")
}

def uploadCookbook(name) {
  def cookbookVersion = versionAndName()
  def action
  def verifyCookbook = dockerRun(script: "knife cookbook show ${name}", returnStatus: true, returnStdout: false)
  if (verifyCookbook != 0) {
    echo "Cookbook ${name} not found. Continuing with initial upload..."
    action = 'upload'
  }
  else {
    action = checkCookbookVersion(name, cookbookVersion)
  }
  if (action == 'upload' || action == 'update') {
    berksUpload()
    echo 'Upload complete.'
  }
  else if (action == 'skip')  {
    echo 'Nothing to do.'
  }
  else {
    error('Could not determine next action, aborted...')
  }
}

def berksUpload(berksBinary) {
  // Grant permissions to access the repository from inside the container.
  sh('chmod a=rwX .')
  dockerRun(script: "sh -c 'berks install && berks upload'", returnStatus: false, returnStdout: false)
}

def versionAndName() {
  def metadata = readFile('metadata.rb')
  def pattern = /version\s*\'(\d+\.\d+\.\d+)\'/
  def matcher = metadata  =~ pattern
  def result =  matcher[0][1]
  result
}

def checkCookbookVersion(name, newVersion) {
  def currentVersion = dockerRun(script: "knife cookbook show ${name}", returnStatus: false, returnStdout: true)
  def pattern = /^\S*\s{1}(\d+\.\d+\.\d+)/
  def matcher = currentVersion  =~ pattern
  def result =  matcher[0][1]

  def parseVersion = { version ->
    def parts = version.split('\\.').collect { it as int }
    [major: parts[0], minor: parts[1], patch: parts[2]]
  }
  def current = parseVersion(result)
  def newVer = parseVersion(newVersion)

  if (current.major == newVer.major && current.minor == newVer.minor && current.patch == newVer.patch) {
    echo 'Newer cookbook version was not found!'
    return 'skip'
  } else if (current.major < newVer.major || 
             (current.major == newVer.major && current.minor < newVer.minor) || 
             (current.major == newVer.major && current.minor == newVer.minor && current.patch < newVer.patch)) {
    echo 'Newer cookbook version detected. Continuing...'
    return 'update'
  }
  error("Version comparison failed: Current version ${result}, New version ${newVersion}")
}
