/*
Config mandatory properties:
name
path
type

Optional properties:
slack_channel
aws_profile
hasLinter Default false
integrationTestsEnabled default false
enforceProjectName default false
buildPythonPackage default true
*/
def call(body) {
  def config = [:]
  body.resolveStrategy = Closure.DELEGATE_FIRST
  body.delegate = config
  body()
  def optional_params = []
  if (!config.containsKey("slack_channel"))            {config.slack_channel   = "delphi-slz-cicd-alerts"}
  if (!config.containsKey("aws_profile"))              {config.aws_profile     = "gdb-delphi-dev"}
  if (!config.containsKey("enforceProjectName"))       {config.enforceProjectName = false}
  if (!config.containsKey("buildPythonPackage"))       {config.buildPythonPackage = true}
  if (!config.containsKey("softwareCatalogFiles"))     {config.softwareCatalogFiles = []}
  if (!config.containsKey("software_catalog_enabled")) {config.software_catalog_enabled = true}

  if (config.buildPythonPackage) {
    optional_params << choice(
      choices: ['default','yes','no'],
      description: 'Whether to build python package. By default it\'s only build for develop, release* and master branches.',
      name: 'BUILD_PYTHON_PACKAGE'
    )
  } else {
    optional_params << choice(
      choices: ['no'],
      description: 'Python package build is disabled',
      name: 'BUILD_PYTHON_PACKAGE'
    )
  }

  if (config.integrationTestsEnabled) {
    optional_params << choice( choices: ['yes','no'], description: "Run integration tests", name: 'RUN_INTEGRATION_TESTS')
  }
  if (config.hasLinter) {
    optional_params << choice( choices: ['default','no','yes'], description: "Run linter test before build", name: 'RUN_LINTER')
  }

  def mandatory_params = [
    choice(
      choices: ['no','yes'],
      description: "Build Python Wheels and push to PyPI.",
      name: "PYTHON_DEPS_BUILD_UPLOAD_MODE"
    ),
    choice(
      choices: ['yes','no'],
      description: 'Run unit tests.',
      name: 'RUN_TESTS'
    ),
    choice(
      choices: ['default','yes','no'],
      description: '''Whether to trigger deployment pipeline(build deployment artifact, create octopus release, deploy it).
      By default it\'s only triggered for develop, release* and master branches.
      ''',
      name: 'TRIGGER_DEPLOY'
    ),
    choice(
      choices: [
        'default',
        'dev',
        'qa',
        'stage',
        'skip_deployment'
      ],
      description: 'Set environment for deployment. Skipped by default master/release*, dev by default for all other branches',
      name: 'DEPLOY_ENV_CHOICE'
    ),
    choice(
      choices: ['error','overwrite','skip_build'],
      description: "Docker image upload mode - ovewrite if the image with such tag already exists, raise error if exists, or skip build part if exists.",
      name: 'IMAGE_UPLOAD_MODE'
    ),
    choice(
      choices: ['error','overwrite','ignore'],
      description: 'Defines whether to raise error, overwrite or ignore if python package of specified version already exists in Pypi.',
      name: 'PYTHON_PACKAGE_UPLOAD_MODE'
    ),
    choice(
      choices: ['yes','no'],
      description: "Don't raise errors in case release already exists",
      name: 'FAIL_IF_RELEASE_EXISTS'
    ),
    booleanParam(
      name: 'SOFTWARE_CATALOG_ENABLED',
      defaultValue: config.software_catalog_enabled,
      description: 'Whether or not to validate/publish a Software Catalog metadata file to Datadog. Publishing will only happen if running on the master/release branches.'
    )
  ]
  properties([parameters(( mandatory_params << optional_params).flatten() )])

  pipeline {
    agent {
      label 'linux-agents'
    }
    options { disableConcurrentBuilds() }
    environment {
      AWS_PROFILE           = "${config.aws_profile}"
      PROJECT_GROUP         = "delphi"
      ECR                   = "${utility.getAccountIdByProfile(env.AWS_PROFILE)}.dkr.ecr.us-east-1.amazonaws.com"
      OCTOPUS_CLI_SERVER    = "https://octopus.delphi.zone"
      OCTOPUS_CLI_API_KEY   = sh(script: "aws secretsmanager get-secret-value --profile gdb-delphi-dev --secret-id 'infra/jenkins/octopus_api_key' --output json | jq -r .SecretString", , returnStdout: true).trim()
      OCTOPUS_CHANNEL       = octopus.setOctoChannel(env.BRANCH_NAME)
      DEPLOY_ENV            = octopus.setDeploymentEnvDelphi(params.DEPLOY_ENV_CHOICE, env.PROJECT_GROUP, env.BRANCH_NAME)
      NOTIFICATIONS_CHANNEL = "${config.slack_channel}"
    }
    stages {
      stage('Validate Software Catalog Definition') {
        when {
          expression { return params.SOFTWARE_CATALOG_ENABLED}
        }
        steps {
          library "jenkins-global-libraries@master"
          script {
            datadogSoftwareCatalogValidate(servicePath: config.path)
            config.softwareCatalogFiles.each {file ->
              datadogSoftwareCatalogValidate(
                servicePath: config.path,
                serviceDefinitionFilePath: file
              )
            }
          }
        }
      }
      stage("Generic build stage") {
        steps {
          script {
            // Filter parameters based on config:
            if (!config.integrationTestsEnabled) { params = params.findAll{entry -> entry.key != "RUN_INTEGRATION_TESTS"} }
            if (!config.hasLinter)               { params = params.findAll{entry -> entry.key != "RUN_LINTER"} }

            println(config)
            println(params)

            parallel(["${config.name}": pythonPackage_v2.getPythonPackageStage(params, config.name, config.path, config.type, config.enforceProjectName)])
          }
        }
      }
      stage('Publish Software Catalog Definition') {
        when {
          allOf {
            anyOf {
              branch 'master'
              branch 'release*'
            }
            expression { return params.SOFTWARE_CATALOG_ENABLED}
          }
        }
        steps {
          script {
            datadogSoftwareCatalogPublish(
              servicePath: config.path,
              fetchAdditionalMetadata: false,
            )
            config.softwareCatalogFiles.each {file ->
              datadogSoftwareCatalogPublish(
                servicePath: config.path,
                serviceDefinitionFilePath: file,
                fetchAdditionalMetadata: false,
              )
            }
          }
        }
      }
    }
    post {
      always {
        sh "sudo chown -R ec2-user:ec2-user ${env.WORKSPACE}"
      }
      success {
        script {
          if (currentBuild.getPreviousBuild() &&
              currentBuild.getPreviousBuild().getResult().toString() != "SUCCESS") {
            utility.slackNotifyMainBranches(currentBuild.currentResult, env.NOTIFICATIONS_CHANNEL)
          }
        }
      }
      failure {
        script {
          utility.slackNotifyMainBranches(currentBuild.currentResult, env.NOTIFICATIONS_CHANNEL)
        }
      }
      cleanup {
          deleteDir()
      }
    }
  }
}
