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

import com.urbancode.air.*
import org.apache.commons.httpclient.*
import org.apache.commons.httpclient.methods.*;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.protocol.*
import org.apache.http.HttpResponse
import org.apache.http.client.methods.HttpGet
import org.apache.http.client.methods.HttpPost
import org.apache.http.entity.StringEntity

import com.urbancode.commons.util.IO

import java.util.regex.Pattern

public class AddComment extends AutomationBase {
    
    //**************************************************************************
    // CLASS
    //**************************************************************************
    
    //**************************************************************************
    // INSTANCE
    //**************************************************************************
    
    String defectKey
    String taskKey
    String usKey
    String comment
    
    def workspaceRef
    def defectIdSet = [] as Set
    def taskIdSet = [] as Set
    def usIdSet = [] as Set
    
    def defectArtifactPattern
    def taskArtifactPattern
    def usArtifactPattern
    
    public void execute() {
        setupHttpClient()
        
        println "Getting Workspace"
        workspaceRef = configureWorkspace()
        println "Workspace Ref = ${workspaceRef}"
        
        try {
            defectIdSet = defectKey.split(",")
            taskIdSet = taskKey.split(",")
            usIdSet = usKey.split(",")

            String issuesXml = createXml()
            
            if (issuesXml) {
                sendPost(issuesXml)
            }
        }
        catch (Exception e) {
            e.printStackTrace()
            System.exit(1)
        }
    }

    private void createXml() {
        if (usIdSet.size() == 0 && taskIdSet.size() == 0 && defectIdSet.size() == 0) {
            println "No Rally artifact references found in build life changes."
        }
        else {
            for (def defectId in defectIdSet) {
                defectId = defectId.trim()
                def defectData = null
                HttpMethod method = null
                def response = null
                def result = null
                
                try {
                   method = new GetMethod(url + "defect?workspace=" + URLEncoder.encode(workspaceRef, "UTF-8") + 
                       "&query=" + URLEncoder.encode("(FormattedID = " + defectId+ ")" ,"UTF-8") + "&" + URLEncoder.encode("fetch", "UTF-8") + 
                           "=" + URLEncoder.encode("true", "UTF-8"))
                   result = client.executeMethod(method)
                   defectData = IO.readText(method.getResponseBodyAsStream())
                }
                finally {
                    if(method != null) {
                       method.releaseConnection();
                    }
                }
                def defectResult = new XmlParser().parseText(defectData).Results.Object;
                if (defectResult.size() > 0) {
                    // Generate XML doc
                    def writer = new StringWriter() 
                    def builder = new groovy.xml.MarkupBuilder(writer) 

                    println "Adding comment for: $defectId"
                    builder.ConversationPost() {
                        Artifact(defectResult.ObjectID[0].text())
                        Text(comment)
                        Workspace(workspaceRef)
                    }
                    
                    sendPost(url, writer.toString())
               }
               else {
                  println "Unable to find Rally defect $defectId"
               }
            }
            for (def taskId in taskIdSet) {
                taskId = taskId.trim()
                def taskData = null
                HttpMethod method = null
                def response = null
                def result = null
                
                try {
                   method = new GetMethod(url + "task?workspace=" + URLEncoder.encode(workspaceRef, "UTF-8") + 
                       "&query=" + URLEncoder.encode("(FormattedID = " + taskId+ ")" ,"UTF-8") + "&" + URLEncoder.encode("fetch", "UTF-8") + 
                           "=" + URLEncoder.encode("true", "UTF-8"))
                   result = client.executeMethod(method)
                   taskData = IO.readText(method.getResponseBodyAsStream())
                }
                finally {
                    if(method != null) {
                       method.releaseConnection();
                    }
                }
                def taskResult = new XmlParser().parseText(taskData).Results.Object;
                if (taskResult.size() > 0) {
                    // Generate XML doc
                    def writer = new StringWriter() 
                    def builder = new groovy.xml.MarkupBuilder(writer) 

                    println "Adding comment for: $taskId"
                    builder.ConversationPost(){
                        Artifact(taskResult.ObjectID[0].text())
                        Text(comment)
                        Workspace(workspaceRef)
                    }
                    
                    sendPost(url, writer.toString())
                }
                else {
                    println "Unable to find Rally task $taskId"
                }
            }
            for (def usId in usIdSet) {
                usId = usId.trim()
                def usData = null
                HttpMethod method = null
                def response = null
                def result = null
                
                try {
                   method = new GetMethod(url + "hierarchicalrequirement?workspace=" + URLEncoder.encode(workspaceRef, "UTF-8") + 
                       "&query=" + URLEncoder.encode("(FormattedID = " + usId+ ")" ,"UTF-8") + "&" + URLEncoder.encode("fetch", "UTF-8") + 
                           "=" + URLEncoder.encode("true", "UTF-8"))
                   result = client.executeMethod(method)
                   usData = IO.readText(method.getResponseBodyAsStream())
                }
                finally {
                    if(method != null) {
                       method.releaseConnection();
                    }
                }
                def usResult = new XmlParser().parseText(usData).Results.Object;
                if (usResult.size() > 0) {
                    // Generate XML doc
                    def writer = new StringWriter() 
                    def builder = new groovy.xml.MarkupBuilder(writer) 

                    println("Adding comment for: $usId")
                    builder.ConversationPost(){
                        Artifact(usResult.ObjectID[0].text())
                        Text(comment)
                        Workspace(workspaceRef)
                    }
                    
                    sendPost(url, writer.toString())
                }
                else {
                    println "Unable to find Rally User Story $usId"
                }
            }
        }
    }
    
    private void sendPost(String postUrl, String xml) {
        HttpPost postMethod = new HttpPost(postUrl + "conversationpost/create") 
        try {
            postMethod.setEntity(new StringEntity(xml));

            def responseCode = client.execute(postMethod)
            InputStream responseStream = postMethod.getResponseBodyAsStream()
            if (isGoodResponseCode(responseCode)) {
                println "Successfully created comment"
                println ""
            }
            else {
                IO.copy(responseStream, System.err)
                throw new RuntimeException("Rally server did not create comment. StatusCode: ${responseCode}")
            }
        }
        finally {
            postMethod.releaseConnection()
        }
    }
    
    private boolean isGoodResponseCode(int responseCode) {
        return responseCode >= 200 && responseCode < 300;
    }
}
