/*
* Licensed Materials - Property of IBM Corp.
* IBM UrbanCode Build
* IBM UrbanCode Deploy
* IBM UrbanCode Release
* IBM AnthillPro
* (c) Copyright IBM Corporation 2002, 2017. 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.integration

import groovy.util.slurpersupport.GPathResult;

import org.apache.commons.io.IOUtils;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.StringEntity
import org.apache.http.HttpEntityEnclosingRequest

import com.urbancode.air.AirPluginTool
import com.urbancode.air.plugin.rtcworkitems.RTCWorkItemHelper;
import com.urbancode.air.XTrustProvider;
import com.urbancode.commons.httpcomponentsutil.HttpClientBuilder;


public class AddComment {

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

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

    String url
    String password
    String username
    String projectName
    String comment
    String workItemId
    String procId
    String compProcId
    String appProcId
    String requestId
    String serverUrl
    String procRequestScope = ""
    boolean addCommentUrl
    def props

    public boolean execute() {
        HttpClientBuilder builder = new HttpClientBuilder();
        builder.setTrustAllCerts(true);
        HttpClient client = builder.buildClient();
        boolean updated = false;

        def rtcHelper = new RTCWorkItemHelper(props);
        def catalogurl = rtcHelper.getCatalogUrl(client);
        rtcHelper.authenticateRTCUser(catalogurl, client);
        def servicesUrl = rtcHelper.getServicesUrl(catalogurl, client);
        def workItemUrl = rtcHelper.getWorkItemUrl(servicesUrl, client);

        if (addCommentUrl == true) {
            if (compProcId) {
                procRequestScope = "#componentProcessRequest"
            }
            else if (appProcId) {
                procRequestScope = "#applicationProcessRequest"
            }
            else if (procId) {
                procRequestScope = "#processRequest"
            }
        }

        try {
            HttpRequestBase method = null
            def response = null
            def createResult;
            def defectXml = rtcHelper.getWorkItemByIdentifier(workItemId, workItemUrl, client, null);
            if (!defectXml) {
                println "[Error] Unable to find work item $workItemId's xml.";
                return updated;
            }
            if (defectXml.attributes()[RTCWorkItemHelper.n_oslc_cm.'totalCount'].equals("1")) {
                //lets add the comment
                def gBuilder = new groovy.xml.StreamingMarkupBuilder()
                def workItemComment = new StringBuilder();
                workItemComment << comment;

                if (!procRequestScope.equals("")) {
                    serverUrl = serverUrl + "/${procRequestScope}/${requestId}"
                    workItemComment << "<br /><br />"
                    workItemComment << "IBM UrbanCode Deploy Deployment Execution: ${serverUrl}"
                }

                println "Adding comment for work item $workItemId";
                gBuilder.encoding = "UTF-8"
                def newComment = {
                    mkp.xmlDeclaration()
                    mkp.declareNamespace('oslc_cm':'http://open-services.net/xmlns/cm/1.0/')
                    mkp.declareNamespace('rtc_cm':'http://jazz.net/xmlns/prod/jazz/rtc/cm/1.0/')
                    mkp.declareNamespace('dc': 'http://purl.org/dc/terms/')
                    'rtc_cm:Comment'{
                        'dc:description'(workItemComment);
                    }
                }
                //get the post url
                def commentUrl =
                        defectXml[RTCWorkItemHelper.n_oslc_cm.ChangeRequest][RTCWorkItemHelper.n_rtc_cm.comments][0]
                                 .attributes()[RTCWorkItemHelper.n_oslc_cm.'collref'];
                //post the new comment
                int attempt = 0
                for (attempt = 0; attempt < 10; attempt++) {
                    try {
                        method = new HttpPost(commentUrl);
                        String newCommentString = gBuilder.bind(newComment);
                        method.setEntity(new StringEntity(newCommentString));
                        method.setHeader("Accept", "application/x-oslc-cm-change-request+xml");
                        method.setHeader("Content-type", "application/x-oslc-cm-change-request+xml");
                        createResult = client.execute(method);
                        int statusCode = createResult.getStatusLine().getStatusCode();
                        if (statusCode < 300 && statusCode >= 200) {
                            println "Successfully added comment to work item ${workItemId}";
                            updated = true
                            break;
                        }
                        else if (statusCode == 409) {
                                println "[Warning] Received 409 status code conflict error... Retry #${attempt+1}"
                        }
                        else {
                            println "Response Output:"
                            println createResult.getEntity().getContent().text;
                            println ""
                            throw new RuntimeException("[Error] Failed to add comment to work item ${workItemId}")
                        }
                    }
                    finally {
                        if (method != null) {
                            method.releaseConnection();
                        }
                    }
                }
                if (attempt >= 10) {
                    throw new RuntimeException("[Error] Too many conflicts when adding the comment to work item ${workItemId}. Please try again.")
                }
            } else {
                println "[Error] Unable to find work item $workItemId";
                return updated;
            }
        }
        catch (Exception e) {
            e.printStackTrace()
        }
        return updated;
    }
}
