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

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

import com.urbancode.air.AirPluginTool
import com.urbancode.air.plugin.jira.addcomments.FailMode
import com.urbancode.air.plugin.jira.addcomments.JIRAHelper
import groovy.json.JsonBuilder
import org.apache.http.impl.client.DefaultHttpClient

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

final def serverUrl         = props['serverUrl']
final def serverVersion     = props['serverVersion']
final def username          = props['username']
final def password          = props['passwordScript']?:props['password']

final def transitionName        = props['transitionName']
final def additionalComment = props['additionalComment']
final def resolutionName    = props['resolutionName']
final def issueIds          = props['issueIds'].split(',').collect {it.trim().replaceAll("\\s","")} as List
issueIds.removeAll("")      // Remove any empty strings
issueIds.unique()         // Remove duplicates
final def failMode          = FailMode.valueOf(props['failMode']);

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

println "Server:\t$serverUrl"
println "Transition:\t$transitionName"
print "Issue Keys:\t"
println issueIds.sort()
println "Additional Comment:\t$additionalComment"
println "Fail mode configured for this step is ${failMode}"
println ""

// Empty JIRAHelper class. Created to call helper methods
JIRAHelper jira = new JIRAHelper()

// Construct the client to allow the authentication of the user
DefaultHttpClient client = jira.createClient(username, password)

// Keeps track of update errors
def errorCount = 0

for (def issueId : issueIds.sort()) {
    try {
        // Confirm the updating issue exists
        if (!jira.doesIssueExist(client, serverUrl, issueId)) {
            errorCount++
            if (failMode == FailMode.FAIL_FAST) {
                throw new IllegalStateException("Fail Fast: Skipped Issue ${issueId}" +
                    ": Specified Issue not found.")
            }
        }
        else {
            // Determine if specified transition is valid
            String transitionID = jira.getTransitionId(client, serverUrl, issueId, transitionName)
            if (!transitionID) {
                errorCount++
                if (failMode == FailMode.FAIL_FAST) {
                    throw new IllegalStateException("Fail Fast: Skipping Issue ${issueId}: " +
                        "Specified Action \"${transitionName}\" was not available.")
                }
            }
            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, else default value will be assigned
                if (jira.isResolutionValid(client, serverUrl, issueId, 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, issueId, updateJSON)) {
                    errorCount++
                    if(failMode == FailMode.FAIL_FAST) {
                        throw new IllegalStateException("Fail Fast: View above output for details.")
                    }
                }
            }
        }
        println "--------------------------"
    }
    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 && !issueIds) {
    throw new IllegalStateException("Fail on no Updates: No issues specified.")
}

// Check if all updates failed
if (failMode == FailMode.FAIL_ON_NO_UPDATES && errorCount == issueIds.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!")
}