/*
* Licensed Materials - Property of IBM Corp.
* IBM UrbanCode Build
* (c) Copyright IBM Corporation 2012, 2014. All Rights Reserved.
*
* U.S. Government Users Restricted Rights - Use, duplication or disclosure restricted by
* GSA ADP Schedule Contract with IBM Corp.
*/

import com.urbancode.air.AirPluginTool
import com.urbancode.air.plugin.automation.JIRAHelper
import com.urbancode.air.plugin.automation.XMLHelper
import com.urbancode.air.plugin.automation.FailMode
import java.lang.reflect.Array;
import groovy.json.JsonBuilder
import org.apache.http.impl.client.CloseableHttpClient

/*
 * JIRA REST API Documentation: https://docs.atlassian.com/jira/REST/latest/
 */

final def apTool = new AirPluginTool(this.args[0], this.args[1])
final def props = apTool.getStepProperties()

final def serverUrl         = props['automation/serverUrl']
final def username          = props['automation/username']
final def password          = props['automation/passwordScript'] ?: props['automation/password']
final def transitionName    = props['transitionName']
final def additionalComment = props['additionalComment']
final def issueIdPattern    = props['issueIdPattern']
final def resolutionName    = props['resolutionName']
final def failMode          = FailMode.valueOf(props['failMode']);


//------------------------------------------------------------------------------
// Script content
//------------------------------------------------------------------------------

println "Server: $serverUrl"
println "Transition: $transitionName"
println "Resolution: $resolutionName"
println "Issue Keys: $issueIdPattern"
println "Additional Comment: $additionalComment"
println "Fail mode configured for this step is ${failMode}"
println ""


def errorCount = 0
def issueIdSet = [] as Set

try {
    JIRAHelper jira = new JIRAHelper()
    CloseableHttpClient client = jira.createClient(username, password)
    try {
        XMLHelper helper = new XMLHelper(issueIdPattern)
        helper.getChangesets()
        issueIdSet = helper.getIssueIdSet()

        issueIdSet.each { issueKey ->
            // Confirm the updating issue exists
            if (!jira.doesIssueExist(client, serverUrl, issueKey)) {
                errorCount++
                def msg = "Skipped Issue ${issueKey}: Specified Issue not found."
                if (failMode == FailMode.FAIL_FAST) {
                    throw new IllegalStateException("Fail Fast: " + msg)
                }
            }
            else {
                // Determine if specified transition is valid
                String transitionID = jira.getTransitionId(client, serverUrl, issueKey, transitionName)
                if (!transitionID) {
                    errorCount++
                    def msg = "Skipping Issue ${issueKey}: Specified Action \"${transitionName}\" was not available."
                    println(msg);
                    if (failMode == FailMode.FAIL_FAST) {
                        throw new IllegalStateException("Fail Fast: " + msg)
                    }
                }
                else {
                    // Issue exists and transition is valid
                    // Create Update REST call body as HashMap object
                    def updateIssueMap = [:]

                    // Append the new transition state the issue will enter
                    def transitionMap = [:]
                    transitionMap.put("id", "${transitionID}")
                    updateIssueMap.put("transition", transitionMap)

                    // Confirm resolutionName is valid
                    if (jira.isResolutionValid(client, serverUrl, issueKey, resolutionName)) {
                        def resolutionMap = [:]
                        resolutionMap.put("name", resolutionName)
                        def fieldsMap = [:]
                        fieldsMap.put("resolution", resolutionMap)
                        updateIssueMap.put("fields", fieldsMap)
                    }

                    // Append a comment that will be posted with the updated transition
                    if (additionalComment) {
                        def addMap = [:]
                        addMap.put("body", additionalComment)
                        def commentMap = [:]
                        commentMap.put("add", addMap)

                        def updateMap = [:]
                        def commentArray = []
                        commentArray << commentMap
                        updateMap.put("comment", commentArray)
                        updateIssueMap.put("update", updateMap)
                    }

                    // Change mapping to JSON and prepare it to be sent via REST call
                    JsonBuilder updateJSON = new JsonBuilder(updateIssueMap)

                    // Call the do transitions REST call
                    if (!jira.updateIssue(client, serverUrl, issueKey, updateJSON)) {
                        errorCount++
                        if(failMode == FailMode.FAIL_FAST) {
                            throw new IllegalStateException("Fail Fast: View above output for details.")
                        }
                    }
                }
            }
        }
    }
    finally {
        client.close()
    }
}
catch (Exception e) {
    e.printStackTrace()
    throw new IllegalStateException("Full execution of update issue failed.")
}

//------------------------------------------------------------------------------
// Check post conditions
//------------------------------------------------------------------------------

// Check if no issues were specified
if (failMode == FailMode.FAIL_ON_NO_UPDATES && !issueIdSet) {
    throw new IllegalStateException("Fail on no Updates: No issues specified.")
}

// Check if all updates failed
if (failMode == FailMode.FAIL_ON_NO_UPDATES && errorCount == issueIdSet.size()) {
    throw new IllegalStateException("Fail on no Updates: All issues failed to update.")
}

if (failMode == FailMode.FAIL_ON_ANY_FAILURE && errorCount > 0) {
    throw new IllegalStateException("Fail On Any Failure: Got ${errorCount} failures!")
}