/*
* 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 ChangeArtifactProperty extends AutomationBase {

    //**************************************************************************
    // CLASS
    //**************************************************************************

    //**************************************************************************
    // INSTANCE
    //**************************************************************************

    String defectType
    String property
    String newValue
    String artifactKey

    public void execute() {
        setupHttpClient()

        if (artifactKey && artifactKey.trim().length() > 0) {
            updateProperty()
        }
        else {
            System.out.println 'No artifacts found to update!';
        }
    }

    private void updateProperty() {
        def workspaceRef = configureWorkspace()

        if(!newValue || newValue.trim().length() == 0) {
            newValue = "";
        }

        String[] newValArray = newValue.split(',');
        String[] artifactArray = artifactKey.split(',');
        if(newValArray.length != 1 &&
                newValArray.length != artifactArray.length) {
            println "The number of New Value items must be 1 or match the number of Artifacts!";
            System.exit(1);
        }

        def isError = false;
        for(int i = 0; i<artifactArray.length; i++) {
            def artifact = artifactArray[i];
            def newVal = newValArray.length == 1 ? newValArray[0] : newValArray[i];

            def writer = new StringWriter();
            def builder = new groovy.xml.MarkupBuilder(writer);
            def typeNode = builder.createNode(defectType);
            def propertyNode = builder.createNode(property, newVal);
            builder.nodeCompleted(typeNode, propertyNode);
            builder.nodeCompleted(null, typeNode);

            def jsonUpdate = new JSONObject()
            def jsonProperty = new JSONObject()
            jsonProperty.put(property,newVal)
            jsonUpdate.put(defectType,jsonProperty)

            if (artifact.trim().length() > 0) {
                def queryUrl = url + defectType.toLowerCase() + "?workspace=" + URLEncoder.encode(workspaceRef, "UTF-8") +
                    "&query=" + URLEncoder.encode("(FormattedID = " + artifact.trim() + ")" ,"UTF-8") + "&" + URLEncoder.encode("fetch", "UTF-8") +
                        "=" + URLEncoder.encode("true", "UTF-8")
                println "Getting artifact info url : $queryUrl"
                //query to get ObjectID from formattedID
                HttpGet queryMethod = new HttpGet(queryUrl)
                def queryResponseResult = client.execute(queryMethod)
                def queryResponseCode = queryResponseResult.statusLine.statusCode
                String responseText = IO.readText(queryResponseResult.entity.content)
                def jsonQueryResult = null
                def queryObjectID = null

                if (isGoodResponseCode(queryResponseCode)) {
                    def queryResult = new JSONObject(responseText).get('QueryResult');
                    def queryErrors = queryResult.get('Errors')
                    def queryWarnings = queryResult.get('Warnings')
                    if(queryErrors.length() == 0 && queryWarnings.length() == 0) {
                        int totalResultCount = queryResult['TotalResultCount']
                        if (totalResultCount == 0) {
                            println "Rally Server could not find the item '$artifact' ! "
                            isError = true
                            break;
                        }
                        else {
                            println "Successfully query item " + artifact;
                            jsonQueryResult = queryResult['Results'].get(0)
                            queryObjectID = jsonQueryResult.get('ObjectID')
                        }
                    }
                    else {
                        println "ERROR!!! Rally Server could not query item " + artifact;
                        println "query url was '$queryUrl'"
                        if (queryErrors.length() > 0) {
                            println "Errors: $queryErrors"
                        }
                        if (queryWarnings.length() > 0) {
                            println "Warnings: $queryWarnings"
                        }
                        isError = true
                        break;
                    }
                }
                else {
                    println "ERROR!!! Rally Server could not query item " + artifact + " by url '$queryUrl'. Error message $responseText"
                }

                //post to update the object in question
                def key = getKey()
                def changeUrl = url + defectType + "/" + queryObjectID + "?key=" + URLEncoder.encode(key, 'UTF-8')
                HttpPost method = new HttpPost(changeUrl)
                method.setEntity(new StringEntity(jsonUpdate.toString()));
                def result = client.execute(method)
                def response = IO.readText(result.entity.content)

                //check results
                def responseCode = result.statusLine.statusCode
                if (isGoodResponseCode(responseCode)) {
                    def changeResult = new JSONObject(response).get('OperationResult')
                    def errors = changeResult.get('Errors')
                    def warnings = changeResult.get('Warnings')
                    if(errors.length() == 0 && warnings.length() == 0 ) {
                        println "Successfully updated item " + artifact + " by url '$changeUrl'";
                    }
                    else {
                        println "ERROR!!! Rally Server could not update item " + artifact + " by url '$changeUrl'";
                        println "Update JSON was : " + jsonUpdate.toString()
                        if (errors.length() > 0) {
                            println "Errors: $errors"
                        }
                        if (warnings.length() > 0) {
                            println "Warnings: $warnings"
                        }
                        isError = true
                        break
                    }
                }
                else {
                    println "ERROR!!! Rally Server could not update item " + artifact + " by url '$changeUrl'. Error message $response" 
                }

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