/*
* 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 java.util.regex.Pattern

import org.apache.http.client.HttpClient
import org.apache.http.client.methods.HttpGet
import org.apache.http.client.methods.HttpPost
import org.apache.http.entity.StringEntity
import org.apache.http.impl.client.DefaultHttpClient

import com.urbancode.commons.httpcomponentsutil.HttpClientBuilder
import com.urbancode.commons.util.IO

public class XMLHelper {

    String issuePattern
    def issueIdSet = [] as Set
    def issueIdToChangeSetListMap = [:]
    DefaultHttpClient client

    public XMLHelper(String issuePattern) {
        this.issuePattern = issuePattern
        HttpClientBuilder clientBuilder = new HttpClientBuilder();
        clientBuilder.setTrustAllCerts(true);
        client = clientBuilder.buildClient();
    }

    public String getChangesets() {
        def authToken = System.getenv("AUTH_TOKEN")
        int buildLifeId = Integer.parseInt(System.getenv("BUILD_LIFE_ID"))

        String webUrl = System.getenv("WEB_URL")
        webUrl += webUrl.endsWith("/") ? "" : "/"
        String changesRequestUrl = webUrl + "rest/buildlife/${buildLifeId}/sourcechanges"

        println "\nGetting source changes from server"

        HttpGet getMethod = new HttpGet(changesRequestUrl);
        if (authToken) {
            getMethod.setHeader("Authorization-Token", authToken)
        }

        String changesXml
        def httpResponse = client.execute(getMethod)
        def responseCode = httpResponse.getStatusLine().getStatusCode()
        if (isGoodResponseCode(responseCode)) {
            changesXml = IO.readText(httpResponse.getEntity().getContent())
            println ""
        }
        else {
            IO.copy(httpResponse.getEntity().getContent(), System.err)
            throw new RuntimeException("Failed to get build life source changes from the server: $changesXml")
        }

        parseChangesets(changesXml)

        return changesXml
    }

    private void parseChangesets(String changesXml) {
        if (!changesXml.contains("change-set")) {
            println "No changes detected."
        }
        else {
            println "Parsing Changelog"

            new XmlSlurper().parseText(changesXml)."change-set".each { changeSetElem ->
                def issueIdPattern = java.util.regex.Pattern.compile(issuePattern)
                def issueMatcher = issueIdPattern.matcher(changeSetElem.'comment'.text());

                while (issueMatcher?.find()) {
                    def issueId
                    if (issueMatcher.groupCount() > 0 ) {
                        // they specified a '(...)' group within the pattern, use that as the issue id
                        issueId = issueMatcher.group(1)
                    }
                    else {
                        // use the whole matching substring as the issue id
                        issueId = issueMatcher.group()
                    }

                    println "Found issue identifier in change comment: $issueId"
                    issueIdSet.add(issueId)
                    def changeSetList = issueIdToChangeSetListMap[issueId]
                    if (!changeSetList) {
                        changeSetList = []
                        issueIdToChangeSetListMap[issueId] = changeSetList
                    }

                    def changeId = changeSetElem."change-id"?.text() ? changeSetElem."change-id".text() : changeSetElem."id".text()
                    changeSetList.add(changeId)
                }
            }
        }
    }

    private void sendPost(String issuesXml) {
        int buildLifeId = Integer.parseInt(System.getenv("BUILD_LIFE_ID"))
        def authToken = System.getenv("AUTH_TOKEN")
        String webUrl = System.getenv("WEB_URL")
        webUrl += webUrl.endsWith("/") ? "" : "/"
        String postUrl = webUrl + "rest/buildlife/${buildLifeId}/issues"

        println "Uploading Issues..."

        HttpPost postMethod = new HttpPost(postUrl);
        if (authToken) {
            postMethod.setHeader("Authorization-Token", authToken)
            postMethod.setHeader("Content-Type", "application/xml")
        }
        postMethod.setEntity(new StringEntity(issuesXml));

        def httpResponse = client.execute(postMethod)
        def responseCode = httpResponse.getStatusLine().getStatusCode()
        if (isGoodResponseCode(responseCode)) {
            println "Success"
        }
        else {
            IO.copy(postMethod.getEntity().getContent(), System.err)
            throw new RuntimeException("JIRA results upload to server failed. StatusCode: ${responseCode}")
        }
    }

    private boolean isGoodResponseCode(int responseCode) {
        return responseCode >= 200 && responseCode < 300;
    }
}