package com.mirantis.mcp

import java.util.zip.GZIPInputStream
import java.util.zip.GZIPOutputStream

@Grab(group='org.yaml', module='snakeyaml', version='1.17')
import org.yaml.snakeyaml.Yaml

/**
 * https://issues.jenkins-ci.org/browse/JENKINS-26481
 * fix groovy List.collect()
 **/
@NonCPS
def constructString(ArrayList options, String keyOption, String separator = ' ') {
    return options.collect { keyOption + it }.join(separator).replaceAll('\n', '')
}

/**
 * Generate current timestamp
 *
 * @param format Defaults to yyyyMMddHHmmss
 */
def getDatetime(format = "yyyyMMddHHmmss") {
    def now = new Date()
    return now.format(format, TimeZone.getTimeZone('UTC'))
}

/**
 * Run tox with or without specified environment
 * @param env String, name of environment
 */
def runTox(String env = null) {
  if (env) {
    sh "tox -v -e ${env}"
  } else {
    sh 'tox -v'
  }
}

/**
 * Convert YAML document to Map object
 * @param data YAML string
 */
@NonCPS
def loadYAML(String data) {
  def yaml = new Yaml()
  return yaml.load(data)
}

/**
 * Convert Map object to YAML string
 * @param map Map object
 */
@NonCPS
def dumpYAML(Map map) {
  def yaml = new Yaml()
  return yaml.dump(map)
}

/**
 * Render jinja template
 * @param templateVars String, A dict, a dict subclass, json or some keyword arguments
 * @param templateFile String, jinja template file path
 * @param resultFile String, result/generate file path
 *
 * Usage example:
 *
 * def common = new com.mirantis.mcp.Common()
 * common.renderJinjaTemplate(
 *     "${NODE_JSON}",
 *     "${WORKSPACE}/inventory/inventory.cfg",
 *     "${WORKSPACE}/inventory/inventory.cfg")
 * where NODE_JSON= data in json format
 */
def renderJinjaTemplate(String templateVars, String templateFile, String resultFile) {

  sh """
    python -c "
import sys
import jinja2
from jinja2 import Template

# Useful for very coarse version differentiation.
PY2 = sys.version_info[0] == 2
PY3 = sys.version_info[0] == 3
PY34 = sys.version_info[0:2] >= (3, 4)

if PY3:
    string_types = str,
else:
    string_types = basestring


def to_bool(a):
    ''' return a bool for the arg '''
    if a is None or type(a) == bool:
        return a
    if isinstance(a, string_types):
        a = a.lower()
    if a in ['yes', 'on', '1', 'true', 1]:
        return True
    else:
        return False


def generate(templateVars, templateFile, resultFile):
    templateLoader = jinja2.FileSystemLoader(searchpath='/')
    templateEnv = jinja2.Environment(loader=templateLoader)
    templateEnv.filters['bool'] = to_bool
    template = templateEnv.get_template(templateFile)
    outputText = template.render(templateVars)
    Template(outputText).stream().dump(resultFile)

generate(${templateVars}, '${templateFile}', '${resultFile}')
"
  cat ${resultFile}
  """
}

/**
 * Run function on k8s cluster
 *
 * @param config LinkedHashMap
 *        config includes next parameters:
 *          - label, pod label
 *          - function, code that should be run on k8s cluster
 *          - jnlpImg, jnlp slave image
 *          - slaveImg, slave image
 *
 * Usage example:
 *
 * def runFunc = new com.mirantis.mcp.Common()
 * runFunc.runOnKubernetes ([
 *   function : this.&buildCalicoContainers,
 *   jnlpImg: 'docker-prod-virtual.docker.mirantis.net/mirantis/jenkins-slave-images/jnlp-slave:latest',
 *   slaveImg : 'sandbox-docker-dev-local.docker.mirantis.net/skulanov/jenkins-slave-images/calico-slave:1'
 * ])
 * // promotion example. In case of promotion we need only jnlp container
 * def runFunc = new com.mirantis.mcp.Common()
 * runFunc.runOnKubernetes ([
 *   jnlpImg: 'docker-prod-virtual.docker.mirantis.net/mirantis/jenkins-slave-images/jnlp-slave:latest',
 *   function : this.&promote_artifacts
 * ])
 */
def runOnKubernetes(LinkedHashMap config) {


  def jenkinsSlaveImg = config.get('slaveImg', 'none')
  def jnlpSlaveImg = config.get('jnlpImg', 'none')
  def lbl = config.get('label', "buildpod.${env.JOB_NAME}.${env.BUILD_NUMBER}".replace('-', '_').replace('/', '_'))
  def toRun = config.get('function', 'none')

  if (jnlpSlaveImg == 'none') {
    error('jnlp Slave image MUST be defined')
  }

  if (toRun == 'none'){
    error('Code that should be run on k8s MUST be passed along with function parameter')
  }

  if (jenkinsSlaveImg == 'none'){
    // we are running jnlp container only, since no jenkinsSlaveImg is specified, so
    // we are in promotion mode
    podTemplate(label: lbl,
      containers: [
          containerTemplate(
              name: 'jnlp',
              image: jnlpSlaveImg,
              args: '${computer.jnlpmac} ${computer.name}'
          )
      ],
      ) {
      node(lbl){
        container('jnlp') {
          toRun()
        }
      }
    }

  } else {
    podTemplate(label: lbl,
      containers: [
          containerTemplate(
              name: 'jnlp',
              image: jnlpSlaveImg,
              args: '${computer.jnlpmac} ${computer.name}'
          ),
          containerTemplate(
              name: 'k8s-slave',
              image: jenkinsSlaveImg,
              alwaysPullImage: false,
              ttyEnabled: true,
              privileged: true
          )
      ],
      ) {
      node(lbl){
        container('k8s-slave') {
          return toRun()
        }
      }
    }
  } //else

}

/**
 * Compress a string with Gzip and encode result with Base64 encoding,
 * useful for wire transfer of large text data over text-based protocols like HTTP
 * @param s string to encode
 * @return base64-encoded gzipped string
*/
def zipBase64(String s){
    def targetStream = new ByteArrayOutputStream()
    def zipStream = new GZIPOutputStream(targetStream)
    zipStream.write(s.getBytes('UTF-8'))
    zipStream.close()
    def zippedBytes = targetStream.toByteArray()
    targetStream.close()
    return zippedBytes.encodeBase64().toString()
}

/**
 * De-compress a base64-encoded gzipped string, reverts result of zipBase64
 * @param compressed base64-endcoded gzipped string
 * @return decoded decompressed string
*/
def unzipBase64(String compressed){
    def inflaterStream = new GZIPInputStream(new ByteArrayInputStream(compressed.decodeBase64()))
    def uncompressedStr = inflaterStream.getText('UTF-8')
    return uncompressedStr
}
