/*
* 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.
*/
package com.urbancode.air.plugin.automation;

import org.apache.commons.httpclient.*
import org.apache.commons.httpclient.methods.*
import org.apache.http.client.methods.HttpGet
import org.apache.http.client.methods.HttpPost
import org.apache.http.entity.StringEntity
import org.codehaus.jettison.json.JSONObject

import com.urbancode.air.*
import com.urbancode.commons.util.IO

public class ChangeDefectStatus extends AutomationBase {
    
    //**************************************************************************
    // CLASS
    //**************************************************************************

    //**************************************************************************
    // INSTANCE
    //**************************************************************************
    
    String defectKey
    String defectType
    String newState
    
    public void execute() {
        setupHttpClient()
        
        if (defectKey && defectKey.trim().length() > 0) {
            updateStatus()
        }
        else {
            println 'No issues found to update!'
        }
    }
    
    private String determineTypeFromId(defectId) {
        if (defectId.startsWith('US')) {
        	return 'HierarchicalRequirement'
        }
        else if (defectId.startsWith('DE')) {
        	return 'Defect'
        }
        else if (defectId.startsWith('TA')) {
        	return 'Task'
        }
        else {
        	throw new Exception("Unrecognized item type when detected by name: $defectId")
    	}
    }
    
    private String getUpdateJson(defectId) {
		def rallyType = ('DetectFromID' == defectType) ? determineTypeFromId(defectId) : defectType.trim()
        def jsonDetails = new JSONObject()
        
        if ('HierarchicalRequirement' == rallyType) {
        	def scheduledState = newState
            if ('Submitted' == newState) {
            	scheduledState = 'Defined'
            }
            else if ('Open' == newState) {
            	scheduledState = 'In-Progress'
            }
            else if ('Fixed' == newState) {
            	scheduledState = 'Completed'
            }
            else if ('Closed' == newState) {
        		scheduledState = 'Accepted'
            }
    		println "Updating $defectId ScheduledState to $scheduledState"
        	jsonDetails.put('ScheduleState', scheduledState)
        }
        else if ('Task' == rallyType) {
        	def actualState = newState
            if ('Submitted' == newState) {
            	actualState = 'Defined'
            }
            else if ('Open' == newState) {
            	actualState = 'In-Progress'
            }
            else if ('Fixed' == newState) {
            	actualState = 'Completed'
            }
            else if ('Closed' == newState) {
        		actualState = 'Completed'
            }
        	println "Updating $defectId State to $actualState"
        	jsonDetails.put('State', actualState)
        }
        else { // 'Defect'
        	println "Updating $defectId State to $newState"
        	jsonDetails.put('State', newState)
    	}
    	
        def jsonUpdate = new JSONObject()
    	jsonUpdate.put(rallyType, jsonDetails)
    	return jsonUpdate.toString()
    }
    
    private void updateStatus() {
        def workspaceRef = configureWorkspace()
        
        def isError = false
        for (defectId in defectKey.split(',')) {
            if (defectId.trim().length() > 0) {
    			def key = getKey()
    			
        		def jsonUpdate = getUpdateJson(defectId)
        		
        		def rallyType = ('DetectFromID' == defectType) ? determineTypeFromId(defectId).toLowerCase() : defectType.trim().toLowerCase()
        		
                String responseText = findItemByName(workspaceRef, rallyType, defectId.trim())
                def objectId = new JSONObject(responseText)['QueryResult']['Results'].get(0)['ObjectID']

                HttpPost method = new HttpPost(url + "${rallyType}/${objectId}?key=" + URLEncoder.encode(key, 'UTF-8'))
                try {
	                method.setEntity(new StringEntity(jsonUpdate, null, null));
		            def response = client.execute(method)
		            def responseCode = response.statusLine.statusCode
	            	def content = IO.readText(response.entity.content)
	
	                //check results
	                def operationResult = new JSONObject(content).get('OperationResult')
	                def errors = operationResult.get('Errors')
	                def warnings = operationResult.get('Warnings')
	    
	            	if (errors.length() == 0 && isGoodResponseCode(responseCode)) {
	                  	println "Successfully updated item " + defectId;
	              		if (warnings.length() > 0) {
	                  		println "Warnings: $warnings"
	              		}
	                }
	                else {
	                  	println "ERROR!!! Failed to update item " + defectId
	                  	if (errors.length() > 0) {
	                  		println "Errors: $errors"
	              		}
	              		if (warnings.length() > 0) {
	                  		println "Warnings: $warnings"
	              		}
	                  	isError = true
	                }
                }
	            finally {
            		method.releaseConnection()
        		}
            }
        }

        if (isError) {
            System.exit 1
        }
    }
}