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

import org.apache.http.message.BasicNameValuePair

import com.urbancode.air.AirPluginTool
import com.urbancode.air.plugin.automation.RallyHelper

// Get step variables
AirPluginTool apTool = new AirPluginTool(this.args[0], this.args[1])
Properties inProps = apTool.getStepProperties()

String rallyUrl    = inProps['rallyUrl']
String rallyVer    = inProps['rallyVer']
String workspace   = inProps['workspace']
String rallyUser   = inProps['rallyUser']
String rallyPass   = inProps['rallyPass']
String rallyApiKey = inProps['rallyApiKey']
String proxyHost   = inProps['proxyHost']
String proxyPort   = inProps['proxyPort']
String proxyPass   = inProps['proxyPass']
String proxyUser   = inProps['proxyUser']

String defectKey = inProps['defectKey']
String newState  = inProps['newState']

// Set up RallyHelper
RallyHelper.setupHttpClient(rallyApiKey, rallyUser, rallyPass, proxyHost, proxyPort, proxyUser, proxyPass)
String workspaceRef = RallyHelper.configureWorkspace(rallyUrl, rallyVer, workspace)

// Change all defect statuses
int successfulChanges = 0
ArrayList<String> defects = RallyHelper.makeList(defectKey)
defects.eachWithIndex { defect, index ->
    println ("\n----- Working on defect ${index + 1} / ${defects.size()} -----")
    if (updateStatus(workspaceRef, rallyVer, defect, newState)) {
        successfulChanges++
    }
}

println ("\n\n----- Summary: ${successfulChanges} / ${defects.size()} defect states successfully changed -----")
if (successfulChanges == defects.size()) {
    println ('[ok]  All defect statuses changed successfully.')
    System.exit(0)
}
else {
    println ('[error]  Not all defect statuses changed.')
    System.exit(1)
}

/**
*  @param workspaceRef The url reference for the workspace
*  @param version The version of the Rally Server
*  @param defect The ID of the defect
*  @param newState The new state to set the defect to
*  @return True if the defect state was successfully changed, false if not
*/
private boolean updateStatus(String workspaceRef, String version, String defect, String newState) {
    // Get Defect ObjectID
    println ("\n[action]  Retrieving ObjectID for defect ${defect}")
    List<BasicNameValuePair> queryParams = new LinkedList<BasicNameValuePair>()
    queryParams.add(new BasicNameValuePair('workspace', workspaceRef))
    queryParams.add(new BasicNameValuePair('query', "(FormattedID = ${defect})"))
    queryParams.add(new BasicNameValuePair('fetch', 'true'))
    String body = RallyHelper.executeHttpGet('Defect', queryParams)

    def artifactId = RallyHelper.getElement(body, 'Results.Object.ObjectID', 'QueryResult.Results.ObjectID')
    if (artifactId) {
        println ("[ok]  artifactId found: ${artifactId}")
    }
    else {
        println ('[error]  Could not determine artifactId')
        System.exit(1)
    }

    // Generate POST content
    HashMap<String, String> children = new HashMap<String, String>()
    children.put('State', newState)
    String updateInfo = RallyHelper.buildPost('Defect', children)

    // Change Defect Status
    println ("\n[action]  Changing state for defect ${defect} to ${newState}...")
    String postResponse = RallyHelper.executeHttpPost('Defect/' + artifactId, updateInfo)

    //Process returned response
    println ('\n[action]  Checking response from Rally Server...')
    RallyHelper.printWarngingsAndErrors(postResponse, 'Operation')

    // Verify change
    println ('\n[action]  Verifying changed state...')
    body = RallyHelper.executeHttpGet("Defect/${artifactId}")
    def actualState = RallyHelper.getElement(body, 'State', 'Defect.State')
    if (!actualState) {
        println ('[error]  Could not determine new state.')
        System.exit(1)
    }
    if (actualState.equals(newState)) {
        println ("[ok]  Successfully updated defect state to ${actualState}")
        return true
    }
    else {
        println ("[error]  State did not update correctly, still ${actualState}")
        return false
    }
}