package com.mirantis.mk

import static groovy.json.JsonOutput.prettyPrint
import static groovy.json.JsonOutput.toJson

import com.cloudbees.groovy.cps.NonCPS
import groovy.json.JsonSlurperClassic

/**
 *
 * Common functions
 *
 */

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

/**
 * Return workspace.
 * Currently implemented by calling pwd so it won't return relevant result in
 * dir context
 */
def getWorkspace(includeBuildNum = false) {
    def workspace = sh script: 'pwd', returnStdout: true
    workspace = workspace.trim()
    if (includeBuildNum) {
        if (!workspace.endsWith("/")) {
            workspace += "/"
        }
        workspace += env.BUILD_NUMBER
    }
    return workspace
}

/**
 * Get UID of jenkins user.
 * Must be run from context of node
 */
def getJenkinsUid() {
    return sh(
        script: 'id -u',
        returnStdout: true
    ).trim()
}

/**
 * Get GID of jenkins user.
 * Must be run from context of node
 */
def getJenkinsGid() {
    return sh(
        script: 'id -g',
        returnStdout: true
    ).trim()
}

/**
 * Returns Jenkins user uid and gid in one list (in that order)
 * Must be run from context of node
 */
def getJenkinsUserIds() {
    return sh(script: "id -u && id -g", returnStdout: true).tokenize("\n")
}

/**
 *
 * Find credentials by ID
 *
 * @param credsId Credentials ID
 * @param credsType Credentials type (optional)
 *
 */
def getCredentialsById(String credsId, String credsType = 'any') {
    def credClasses = [ // ordered by class name
                        sshKey    : com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey.class,
                        cert      : com.cloudbees.plugins.credentials.common.CertificateCredentials.class,
                        password  : com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredentials.class,
                        any       : com.cloudbees.plugins.credentials.impl.BaseStandardCredentials.class,
                        dockerCert: org.jenkinsci.plugins.docker.commons.credentials.DockerServerCredentials.class,
                        file      : org.jenkinsci.plugins.plaincredentials.FileCredentials.class,
                        string    : org.jenkinsci.plugins.plaincredentials.StringCredentials.class,
    ]
    return com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(
        credClasses[credsType],
        jenkins.model.Jenkins.instance
    ).findAll { cred -> cred.id == credsId }[0]
}

/**
 * Get credentials from store
 *
 * @param id Credentials name
 */
def getCredentials(id, cred_type = "username_password") {
    warningMsg('You are using obsolete function. Please switch to use `getCredentialsById()`')

    type_map = [
        username_password: 'password',
        key              : 'sshKey',
    ]

    return getCredentialsById(id, type_map[cred_type])
}

/**
 * Abort build, wait for some time and ensure we will terminate
 */
def abortBuild() {
    currentBuild.build().doStop()
    sleep(180)
    // just to be sure we will terminate
    throw new InterruptedException()
}

/**
 * Print pretty-printed string representation of given item
 * @param item item to be pretty-printed (list, map, whatever)
 */
def prettyPrint(item) {
    println prettify(item)
}

/**
 * Return pretty-printed string representation of given item
 * @param item item to be pretty-printed (list, map, whatever)
 * @return pretty-printed string
 */
def prettify(item) {
    return groovy.json.JsonOutput.prettyPrint(toJson(item)).replace('\\n', System.getProperty('line.separator'))
}

/**
 * Print informational message
 *
 * @param msg
 * @param color Colorful output or not
 */
def infoMsg(msg, color = true) {
    printMsg(msg, "cyan")
}

/**
 * Print informational message
 *
 * @param msg
 * @param color Colorful output or not
 */
def infoSensitivityMsg(msg, color = true, replacing = []) {
    printSensitivityMsg(msg, "cyan", replacing)
}

/**
 * Print error message
 *
 * @param msg
 * @param color Colorful output or not
 */
def errorMsg(msg, color = true) {
    printMsg(msg, "red")
}

/**
 * Print success message
 *
 * @param msg
 * @param color Colorful output or not
 */
def successMsg(msg, color = true) {
    printMsg(msg, "green")
}

/**
 * Print warning message
 *
 * @param msg
 * @param color Colorful output or not
 */
def warningMsg(msg, color = true) {
    printMsg(msg, "yellow")
}

/**
 * Print debug message, this message will show only if DEBUG global variable is present
 * @param msg
 * @param color Colorful output or not
 */
def debugMsg(msg, color = true) {
    // if debug property exists on env, debug is enabled
    if (env.getEnvironment().containsKey('DEBUG') && env['DEBUG'] == "true") {
        printMsg("[DEBUG] ${msg}", "red")
    }
}

def getColorizedString(msg, color) {
    def colorMap = [
        'red'   : '\u001B[31m',
        'black' : '\u001B[30m',
        'green' : '\u001B[32m',
        'yellow': '\u001B[33m',
        'blue'  : '\u001B[34m',
        'purple': '\u001B[35m',
        'cyan'  : '\u001B[36m',
        'white' : '\u001B[37m',
        'reset' : '\u001B[0m'
    ]

    return "${colorMap[color]}${msg}${colorMap.reset}"
}

/**
 * Print message
 *
 * @param msg Message to be printed
 * @param color Color to use for output
 */
def printMsg(msg, color) {
    print getColorizedString(msg, color)
}

/**
 * Print sensitivity message
 *
 * @param msg Message to be printed
 * @param color Color to use for output
 * @param replacing List with maps for deletion (passwords, logins, etc).
 *                  The first () matching is mandatory !
 *                  Example:
 *                  [/ (OS_PASSWORD=)(.*?)+ /,
 *                   / (password = )(.*?)+ /,
 *                   / (password )(.*?) / ]
 */
def printSensitivityMsg(msg, color, replacing = []) {
    for (i in replacing) {
        msg = msg.replaceAll(i, ' $1XXXXXX ')
    }
    printMsg(msg, color)
}

/**
 * Traverse directory structure and return list of files
 *
 * @param path Path to search
 * @param type Type of files to search (groovy.io.FileType.FILES)
 */
@NonCPS
def getFiles(path, type = groovy.io.FileType.FILES) {
    files = []
    new File(path).eachFile(type) {
        files[] = it
    }
    return files
}

/**
 * Helper method to convert map into form of list of [key,value] to avoid
 * unserializable exceptions
 *
 * @param m Map
 */
@NonCPS
def entries(m) {
    m.collect { k, v -> [k, v] }
}

/**
 * Opposite of build-in parallel, run map of steps in serial
 *
 * @param steps Map of String<name>: CPSClosure2<step> (or list of closures)
 */
def serial(steps) {
    stepsArray = entries(steps)
    for (i = 0; i < stepsArray.size; i++) {
        def step = stepsArray[i]
        def dummySteps = [:]
        def stepKey
        if (step[1] instanceof List || step[1] instanceof Map) {
            for (j = 0; j < step[1].size(); j++) {
                if (step[1] instanceof List) {
                    stepKey = j
                } else if (step[1] instanceof Map) {
                    stepKey = step[1].keySet()[j]
                }
                dummySteps.put("step-${step[0]}-${stepKey}", step[1][stepKey])
            }
        } else {
            dummySteps.put(step[0], step[1])
        }
        parallel dummySteps
    }
}

/**
 * Partition given list to list of small lists
 * @param inputList input list
 * @param partitionSize (partition size, optional, default 5)
 */
def partitionList(inputList, partitionSize = 5) {
    List<List<String>> partitions = new ArrayList<>();
    for (int i = 0; i < inputList.size(); i += partitionSize) {
        partitions.add(new ArrayList<String>(inputList.subList(i, Math.min(i + partitionSize, inputList.size()))));
    }
    return partitions
}

/**
 * Get password credentials from store
 *
 * @param id Credentials name
 */
def getPasswordCredentials(id) {
    return getCredentialsById(id, 'password')
}

/**
 * Get SSH credentials from store
 *
 * @param id Credentials name
 */
def getSshCredentials(id) {
    return getCredentialsById(id, 'sshKey')
}

/**
 * Tests Jenkins instance for existence of plugin with given name
 * @param pluginName plugin short name to test
 * @return boolean result
 */
@NonCPS
def jenkinsHasPlugin(pluginName) {
    return Jenkins.instance.pluginManager.plugins.collect { p -> p.shortName }.contains(pluginName)
}

@NonCPS
def _needNotification(notificatedTypes, buildStatus, jobName) {
    if (notificatedTypes && notificatedTypes.contains("onchange")) {
        if (jobName) {
            def job = Jenkins.instance.getItem(jobName)
            def numbuilds = job.builds.size()
            if (numbuilds > 0) {
                //actual build is first for some reasons, so last finished build is second
                def lastBuild = job.builds[1]
                if (lastBuild) {
                    if (lastBuild.result.toString().toLowerCase().equals(buildStatus)) {
                        println("Build status didn't changed since last build, not sending notifications")
                        return false;
                    }
                }
            }
        }
    } else if (!notificatedTypes.contains(buildStatus)) {
        return false;
    }
    return true;
}

/**
 * Send notification to all enabled notifications services
 * @param buildStatus message type (success, warning, error), null means SUCCESSFUL
 * @param msgText message text
 * @param enabledNotifications list of enabled notification types, types: slack, hipchat, email, default empty
 * @param notificatedTypes types of notifications will be sent, default onchange - notificate if current build result not equal last result;
 *                         otherwise use - ["success","unstable","failed"]
 * @param jobName optional job name param, if empty env.JOB_NAME will be used
 * @param buildNumber build number param, if empty env.BUILD_NUM will be used
 * @param buildUrl build url param, if empty env.BUILD_URL will be used
 * @param mailFrom mail FROM param, if empty "jenkins" will be used, it's mandatory for sending email notifications
 * @param mailTo mail TO param, it's mandatory for sending email notifications, this option enable mail notification
 */
def sendNotification(buildStatus, msgText = "", enabledNotifications = [], notificatedTypes = ["onchange"], jobName = null, buildNumber = null, buildUrl = null, mailFrom = "jenkins", mailTo = null) {
    // Default values
    def colorName = 'blue'
    def colorCode = '#0000FF'
    def buildStatusParam = buildStatus != null && buildStatus != "" ? buildStatus : "SUCCESS"
    def jobNameParam = jobName != null && jobName != "" ? jobName : env.JOB_NAME
    def buildNumberParam = buildNumber != null && buildNumber != "" ? buildNumber : env.BUILD_NUMBER
    def buildUrlParam = buildUrl != null && buildUrl != "" ? buildUrl : env.BUILD_URL
    def subject = "${buildStatusParam}: Job '${jobNameParam} [${buildNumberParam}]'"
    def summary = "${subject} (${buildUrlParam})"

    if (msgText != null && msgText != "") {
        summary += "\n${msgText}"
    }
    if (buildStatusParam.toLowerCase().equals("success")) {
        colorCode = "#00FF00"
        colorName = "green"
    } else if (buildStatusParam.toLowerCase().equals("unstable")) {
        colorCode = "#FFFF00"
        colorName = "yellow"
    } else if (buildStatusParam.toLowerCase().equals("failure")) {
        colorCode = "#FF0000"
        colorName = "red"
    }
    if (_needNotification(notificatedTypes, buildStatusParam.toLowerCase(), jobNameParam)) {
        if (enabledNotifications.contains("slack") && jenkinsHasPlugin("slack")) {
            try {
                slackSend color: colorCode, message: summary
            } catch (Exception e) {
                println("Calling slack plugin failed")
                e.printStackTrace()
            }
        }
        if (enabledNotifications.contains("hipchat") && jenkinsHasPlugin("hipchat")) {
            try {
                hipchatSend color: colorName.toUpperCase(), message: summary
            } catch (Exception e) {
                println("Calling hipchat plugin failed")
                e.printStackTrace()
            }
        }
        if (enabledNotifications.contains("email") && mailTo != null && mailTo != "" && mailFrom != null && mailFrom != "") {
            try {
                mail body: summary, from: mailFrom, subject: subject, to: mailTo
            } catch (Exception e) {
                println("Sending mail plugin failed")
                e.printStackTrace()
            }
        }
    }
}

/**
 * Execute linux command and catch nth element
 * @param cmd command to execute
 * @param index index to retrieve
 * @return index-th element
 */

def cutOrDie(cmd, index) {
    def common = new com.mirantis.mk.Common()
    def output
    try {
        output = sh(script: cmd, returnStdout: true)
        def result = output.tokenize(" ")[index]
        return result;
    } catch (Exception e) {
        common.errorMsg("Failed to execute cmd: ${cmd}\n output: ${output}")
    }
}

/**
 * Check variable contains keyword
 * @param variable keywork is searched (contains) here
 * @param keyword string to look for
 * @return True if variable contains keyword (case insensitive), False if do not contains or any of input isn't a string
 */

def checkContains(variable, keyword) {
    if (env.getEnvironment().containsKey(variable)) {
        return env[variable] && env[variable].toLowerCase().contains(keyword.toLowerCase())
    } else {
        return false
    }
}

/**
 * Parse JSON string to hashmap
 * @param jsonString input JSON string
 * @return created hashmap
 */
def parseJSON(jsonString) {
    def m = [:]
    def lazyMap = new JsonSlurperClassic().parseText(jsonString)
    m.putAll(lazyMap)
    return m
}

/**
 *
 * Deep merge of  Map items. Merges variable number of maps in to onto.
 *   Using the following rules:
 *     - Lists are appended
 *     - Maps are updated
 *     - other object types are replaced.
 *
 *
 * @param onto Map object to merge in
 * @param overrides Map objects to merge to onto
*/
def mergeMaps(Map onto, Map... overrides){
    if (!overrides){
        return onto
    }
    else if (overrides.length == 1) {
        overrides[0]?.each { k, v ->
            if (v in Map && onto[k] in Map){
                mergeMaps((Map) onto[k], (Map) v)
            } else if (v in List) {
                onto[k] += v
            } else {
                onto[k] = v
            }
        }
        return onto
    }
    return overrides.inject(onto, { acc, override -> mergeMaps(acc, override ?: [:]) })
}

/**
 * Test pipeline input parameter existence and validity (not null and not empty string)
 * @param paramName input parameter name (usually uppercase)
  */
def validInputParam(paramName) {
    if (paramName instanceof java.lang.String) {
        return env.getEnvironment().containsKey(paramName) && env[paramName] != null && env[paramName] != ""
    }
    return false
}

/**
 * Take list of hashmaps and count number of hashmaps with parameter equals eq
 * @param lm list of hashmaps
 * @param param define parameter of hashmap to read and compare
 * @param eq desired value of hashmap parameter
 * @return count of hashmaps meeting defined condition
 */

@NonCPS
def countHashMapEquals(lm, param, eq) {
    return lm.stream().filter { i -> i[param].equals(eq) }.collect(java.util.stream.Collectors.counting())
}

/**
 * Execute shell command and return stdout, stderr and status
 *
 * @param cmd Command to execute
 * @return map with stdout, stderr, status keys
 */

def shCmdStatus(cmd) {
    // Set +x , to hide odd messages about temp file manipulations
    def res = [:]
    def stderr = sh(script: 'set +x ; mktemp', returnStdout: true).trim()
    def stdout = sh(script: 'set +x ; mktemp', returnStdout: true).trim()

    try {
        def status = sh(script: "${cmd} 1>${stdout} 2>${stderr}", returnStatus: true)
        res['stderr'] = sh(script: "set +x; cat ${stderr}", returnStdout: true).trim()
        res['stdout'] = sh(script: "set +x; cat ${stdout}", returnStdout: true).trim()
        res['status'] = status
    } finally {
        sh(script: "set +x; rm ${stderr}")
        sh(script: "set +x; rm ${stdout}")
    }

    return res
}

/**
 * Retry commands passed to body
 *
 * Don't use common.retry method for retrying salt.enforceState method. Use retries parameter
 * built-in the salt.enforceState method instead to ensure correct functionality.
 *
 * @param times Number of retries
 * @param delay Delay between retries (in seconds)
 * @param body Commands to be in retry block
 * @return calling commands in body
 * @example retry ( 3 , 5 ) { function body }*          retry{ function body }
 */

def retry(int times = 5, int delay = 0, Closure body) {
    int retries = 0
    while (retries++ < times) {
        try {
            return body.call()
        } catch (e) {
            errorMsg(e.toString())
            sleep(delay)
        }
    }
    throw new Exception("Failed after $times retries")
}

/**
 * Wait for user input with timeout
 *
 * @param timeoutInSeconds Timeout
 * @param options Options for input widget
 */
def waitForInputThenPass(timeoutInSeconds, options = [message: 'Ready to go?']) {
    def userInput = true
    try {
        timeout(time: timeoutInSeconds, unit: 'SECONDS') {
            userInput = input options
        }
    } catch (err) { // timeout reached or input false
        def user = err.getCauses()[0].getUser()
        if ('SYSTEM' == user.toString()) { // SYSTEM means timeout.
            println("Timeout, proceeding")
        } else {
            userInput = false
            println("Aborted by: [${user}]")
            throw err
        }
    }
    return userInput
}

/**
 * Function receives Map variable as input and sorts it
 * by values ascending. Returns sorted Map
 * @param _map Map variable
 */
@NonCPS
def SortMapByValueAsc(_map) {
    def sortedMap = _map.sort { it.value }
    return sortedMap
}

/**
 *  Compare 'old' and 'new' dir's recursively
 * @param diffData =' Only in new/XXX/infra: secrets.yml
 Files old/XXX/init.yml and new/XXX/init.yml differ
 Only in old/XXX/infra: secrets11.yml '
 *
 * @return
 *   - new:
 - XXX/secrets.yml
 - diff:
 - XXX/init.yml
 - removed:
 - XXX/secrets11.yml

 */
def diffCheckMultidir(diffData) {
    common = new com.mirantis.mk.Common()
    // Some global constants. Don't change\move them!
    keyNew = 'new'
    keyRemoved = 'removed'
    keyDiff = 'diff'
    def output = [
        new    : [],
        removed: [],
        diff   : [],
    ]
    String pathSep = '/'
    diffData.each { line ->
        def job_file = ''
        def job_type = ''
        if (line.startsWith('Files old/')) {
            job_file = new File(line.replace('Files old/', '').tokenize()[0])
            job_type = keyDiff
        } else if (line.startsWith('Only in new/')) {
            // get clean normalized filepath, under new/
            job_file = new File(line.replace('Only in new/', '').replace(': ', pathSep)).toString()
            job_type = keyNew
        } else if (line.startsWith('Only in old/')) {
            // get clean normalized filepath, under old/
            job_file = new File(line.replace('Only in old/', '').replace(': ', pathSep)).toString()
            job_type = keyRemoved
        } else {
            common.warningMsg("Not parsed diff line: ${line}!")
        }
        if (job_file != '') {
            output[job_type].push(job_file)
        }
    }
    return output
}

/**
 * Compare 2 folder, file by file
 * Structure should be:
 * ${compRoot}/
 └── diff - diff results will be save here
 ├── new  - input folder with data
 ├── old  - input folder with data
 ├── pillar.diff - globall diff will be saved here
 * b_url - usual env.BUILD_URL, to be add into description
 * grepOpts -   General grep cmdline; Could be used to pass some magic
 *              regexp into after-diff listing file(pillar.diff)
 *              Example: '-Ev infra/secrets.yml'
 * return - html-based string
 * TODO: allow to specify subdir for results?
 **/

def comparePillars(compRoot, b_url, grepOpts) {

    // Some global constants. Don't change\move them!
    keyNew = 'new'
    keyRemoved = 'removed'
    keyDiff = 'diff'
    def diff_status = 0
    // FIXME
    httpWS = b_url + '/artifact/'
    dir(compRoot) {
        // If diff empty - exit 0
        diff_status = sh(script: 'diff -q -r old/ new/  > pillar.diff',
            returnStatus: true,
        )
    }
    // Unfortunately, diff not able to work with dir-based regexp
    if (diff_status == 1 && grepOpts) {
        dir(compRoot) {
            grep_status = sh(script: """
                cp -v pillar.diff pillar_orig.diff
                grep ${grepOpts} pillar_orig.diff  > pillar.diff
                """,
                returnStatus: true
            )
            if (grep_status == 1) {
                warningMsg("Grep regexp ${grepOpts} removed all diff!")
                diff_status = 0
            }
        }
    }
    // Set job description
    description = ''
    if (diff_status == 1) {
        // Analyse output file and prepare array with results
        String data_ = readFile file: "${compRoot}/pillar.diff"
        def diff_list = diffCheckMultidir(data_.split("\\r?\\n"))
        infoMsg(diff_list)
        dir(compRoot) {
            if (diff_list[keyDiff].size() > 0) {
                if (!fileExists('diff')) {
                    sh('mkdir -p diff')
                }
                description += '<b>CHANGED</b><ul>'
                infoMsg('Changed items:')
                def stepsForParallel = [:]
                stepsForParallel.failFast = true
                diff_list[keyDiff].each {
                    stepsForParallel.put("Differ for:${it}",
                        {
                            // We don't want to handle sub-dirs structure. So, simply make diff 'flat'
                            def item_f = it.toString().replace('/', '_')
                            description += "<li><a href=\"${httpWS}/diff/${item_f}/*view*/\">${it}</a></li>"
                            // Generate diff file
                            def diff_exit_code = sh([
                                script      : "diff -U 50 old/${it} new/${it} > diff/${item_f}",
                                returnStdout: false,
                                returnStatus: true,
                            ])
                            // catch normal errors, diff should always return 1
                            if (diff_exit_code != 1) {
                                error 'Error with diff file generation'
                            }
                        })
                }

                parallel stepsForParallel
            }
            if (diff_list[keyNew].size() > 0) {
                description += '<b>ADDED</b><ul>'
                for (item in diff_list[keyNew]) {
                    description += "<li><a href=\"${httpWS}/new/${item}/*view*/\">${item}</a></li>"
                }
            }
            if (diff_list[keyRemoved].size() > 0) {
                description += '<b>DELETED</b><ul>'
                for (item in diff_list[keyRemoved]) {
                    description += "<li><a href=\"${httpWS}/old/${item}/*view*/\">${item}</a></li>"
                }
            }

        }
    }

    if (description != '') {
        dir(compRoot) {
            archiveArtifacts([
                artifacts        : '**',
                allowEmptyArchive: true,
            ])
        }
        return description.toString()
    } else {
        return '<b>No job changes</b>'
    }
}

/**
 * Simple function, to get basename from string.
 * line - path-string
 * remove_ext - string, optionl. Drop file extenstion.
 **/
def GetBaseName(line, remove_ext) {
    filename = line.toString().split('/').last()
    if (remove_ext && filename.endsWith(remove_ext.toString())) {
        filename = filename.take(filename.lastIndexOf(remove_ext.toString()))
    }
    return filename
}

/**
 * Return colored string of specific stage in stageMap
 *
 * @param stageMap LinkedHashMap object.
 * @param stageName The name of current stage we are going to execute.
 * @param color Text color
 * */
def getColoredStageView(stageMap, stageName, color) {
    def stage = stageMap[stageName]
    def banner = []
    def currentStageIndex = new ArrayList<String>(stageMap.keySet()).indexOf(stageName)
    def numberOfStages = stageMap.keySet().size() - 1

    banner.add(getColorizedString(
        "=========== Stage ${currentStageIndex}/${numberOfStages}: ${stageName} ===========", color))
    for (stage_item in stage.keySet()) {
        banner.add(getColorizedString(
            "${stage_item}: ${stage[stage_item]}", color))
    }
    banner.add('\n')

    return banner
}

/**
 * Pring stageMap to console with specified color
 *
 * @param stageMap LinkedHashMap object with stages information.
 * @param currentStage The name of current stage we are going to execute.
 *
 * */
def printCurrentStage(stageMap, currentStage) {
    print getColoredStageView(stageMap, currentStage, "cyan").join('\n')
}

/**
 * Pring stageMap to console with specified color
 *
 * @param stageMap LinkedHashMap object.
 * @param baseColor Text color (default white)
 * */
def printStageMap(stageMap, baseColor = "white") {
    def banner = []
    def index = 0
    for (stage_name in stageMap.keySet()) {
        banner.addAll(getColoredStageView(stageMap, stage_name, baseColor))
    }
    print banner.join('\n')
}

/**
 * Wrap provided code in stage, and do interactive retires if needed.
 *
 * @param stageMap LinkedHashMap object with stages information.
 * @param currentStage The name of current stage we are going to execute.
 * @param target Target host to execute stage on.
 * @param interactive Boolean flag to specify if interaction with user is enabled.
 * @param body Command to be in stage block.
 * */
def stageWrapper(stageMap, currentStage, target, interactive = true, Closure body) {
    def common = new com.mirantis.mk.Common()
    def banner = []

    printCurrentStage(stageMap, currentStage)

    stage(currentStage) {
      if (interactive){
        input message: getColorizedString("We are going to execute stage \'${currentStage}\' on the following target ${target}.\nPlease review stage information above.", "yellow")
      }
      try {
        stageMap[currentStage]['Status'] = "SUCCESS"
        return body.call()
      } catch (Exception err) {
        def msg = "Stage ${currentStage} failed with the following exception:\n${err}"
        print getColorizedString(msg, "yellow")
        common.errorMsg(err)
        if (interactive) {
          input message: getColorizedString("Please make sure problem is fixed to proceed with retry. Ready to proceed?", "yellow")
          stageMap[currentStage]['Status'] = "RETRYING"
          stageWrapper(stageMap, currentStage, target, interactive, body)
        } else {
          error(msg)
        }
      }
    }
}

/**
 *  Ugly transition solution for internal tests.
 *  1) Check input => transform to static result, based on runtime and input
 *  2) Check remote-binary repo for exact resource
 */

def checkRemoteBinary(LinkedHashMap config, List extraScmExtensions = []) {
    def common = new com.mirantis.mk.Common()
    res = [:]
    res['MirrorRoot'] = config.get('globalMirrorRoot', env["BIN_MIRROR_ROOT"] ? env["BIN_MIRROR_ROOT"] : "http://mirror.mirantis.com/")
    // Reclass-like format's. To make life eazy!
    res['mcp_version'] = config.get('mcp_version', env["BIN_APT_MCP_VERSION"] ? env["BIN_APT_MCP_VERSION"] : 'nightly')
    res['linux_system_repo_url'] = config.get('linux_system_repo_url', env["BIN_linux_system_repo_url"] ? env["BIN_linux_system_repo_url"] : "${res['MirrorRoot']}/${res['mcp_version']}/")

    if (config.get('verify', true)) {
        MirrorRootStatus = sh(script: "wget  --auth-no-challenge --spider ${res['linux_system_repo_url']} 2>/dev/null", returnStatus: true)
        if (MirrorRootStatus != 0) {
            common.warningMsg("Resource: ${res['linux_system_repo_url']} not exist")
            res['linux_system_repo_url'] = false
        }
    }
    return res
}

/**
 *  Workaround to update env properties, like GERRIT_* vars,
 *  which should be passed from upstream job to downstream.
 *  Will not fail entire job in case any issues.
 *  @param envVar - EnvActionImpl env job
 *  @param extraVars - Multiline YAML text with extra vars
 */
def mergeEnv(envVar, extraVars) {
    def common = new com.mirantis.mk.Common()
    try {
        def extraParams = readYaml text: extraVars
        for(String key in extraParams.keySet()) {
            envVar[key] = extraParams[key]
            common.warningMsg("Parameter ${key} is updated from EXTRA vars.")
        }
    } catch (Exception e) {
        common.errorMsg("Can't update env parameteres, because: ${e.toString()}")
    }
}

/**
 * Wrapper around parallel pipeline function
 * with ability to restrict number of parallel threads
 * running simultaneously
 *
 * @param branches - Map with Clousers to be executed
 * @param maxParallelJob - Integer number of parallel threads allowed
 *                         to run simultaneously
 */
def runParallel(branches, maxParallelJob = 10) {
    def runningSteps = 0
    branches.each { branchName, branchBody ->
        if (branchBody instanceof Closure) {
            branches[branchName] = {
                while (!(runningSteps < maxParallelJob)) {
                    continue
                }
                runningSteps += 1
                branchBody.call()
                runningSteps -= 1
            }
        }
    }
    if (branches) {
        parallel branches
    }
}

/**
 * Ugly processing basic funcs with /etc/apt
 * @param repoConfig YAML text or Map
 * Example :
 repoConfig = '''
 ---
 aprConfD: |-
   APT::Get::AllowUnauthenticated 'true';
 repo:
   mcp_saltstack:
     source: "deb [arch=amd64] http://mirror.mirantis.com/nightly/saltstack-2017.7/xenial xenial main"
     pin:
       - package: "libsodium18"
         pin: "release o=SaltStack"
         priority: 50
       - package: "*"
         pin: "release o=SaltStack"
         priority: "1100"
     repo_key: "http://mirror.mirantis.com/public.gpg"
 '''
 *
 */

def debianExtraRepos(repoConfig) {
    def config = null
    if (repoConfig instanceof Map) {
        config = repoConfig
    } else {
        config = readYaml text: repoConfig
    }
    if (config.get('repo', false)) {
        for (String repo in config['repo'].keySet()) {
            source = config['repo'][repo]['source']
            warningMsg("Write ${source} >  /etc/apt/sources.list.d/${repo}.list")
            sh("echo '${source}' > /etc/apt/sources.list.d/${repo}.list")
            if (config['repo'][repo].containsKey('repo_key')) {
                key = config['repo'][repo]['repo_key']
                sh("wget -O - '${key}' | apt-key add -")
            }
            if (config['repo'][repo]['pin']) {
                def repoPins = []
                for (Map pin in config['repo'][repo]['pin']) {
                    repoPins.add("Package: ${pin['package']}")
                    repoPins.add("Pin: ${pin['pin']}")
                    repoPins.add("Pin-Priority: ${pin['priority']}")
                    // additional empty line between pins
                    repoPins.add('\n')
                }
                if (repoPins) {
                    repoPins.add(0, "### Extra ${repo} repo pin start ###")
                    repoPins.add("### Extra ${repo} repo pin end ###")
                    repoPinning = repoPins.join('\n')
                    warningMsg("Adding pinning \n${repoPinning}\n => /etc/apt/preferences.d/${repo}")
                    sh("echo '${repoPinning}' > /etc/apt/preferences.d/${repo}")
                }
            }
        }
    }
    if (config.get('aprConfD', false)) {
        for (String pref in config['aprConfD'].tokenize('\n')) {
            warningMsg("Adding ${pref} => /etc/apt/apt.conf.d/99setupAndTestNode")
            sh("echo '${pref}' >> /etc/apt/apt.conf.d/99setupAndTestNode")
        }
        sh('cat /etc/apt/apt.conf.d/99setupAndTestNode')
    }
}
