/*
* 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.test.mstest
import org.apache.http.HttpResponse
import org.apache.http.client.HttpClient
import org.apache.http.client.methods.HttpPost
import org.apache.http.entity.StringEntity

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

public class XMLHelper {
    
    //**************************************************************************
    // CLASS
    //**************************************************************************

    //**************************************************************************
    // INSTANCE
    //**************************************************************************
    private def testCount = 0
    private def suiteCount = 0
    
    public XMLHelper() {
    }
    
    def uploadResult (reportFiles, reportName) {
        testCount = 0
        suiteCount = 0
        
        def reportXml = new java.io.StringWriter()
        
        new groovy.xml.MarkupBuilder(reportXml).
        'test-report'("name": reportName, 
            "type": 'MSTest', 
            "job-id": System.getenv('JOB_ID')) {
                reportFiles.each { file ->
                    println("Parsing " + file.absolutePath)
                    def handler = new MSTestHandler(file)
                    def suiteToTestResults = handler.readTests()
                    suiteCount += suiteToTestResults.size()

                    suiteToTestResults.each { suiteName, testResults ->
                        'test-suite'(name: suiteName) {
                            testResults.each { result ->
                                testCount++
                                test("name": result.testName, "class-name": result.className, "result": result.testResult,
                                        "time": result.testDuration) {
                                    result.messages.each {
                                        message(it)
                                    }
                                }
                            }
                        }
                    }

                }
            }
        
        if (reportXml) {
            sendPostRequest(reportName, reportXml.toString())
        }
        else {
            println 'No report was able to be generated'
        }
    }
    
    private void sendPostRequest(String name, String xml) {
        def authToken = System.getenv("AUTH_TOKEN")
        String buildLifeId = System.getenv("BUILD_LIFE_ID")
        name = encode(name)
        
        // construct the URL with property replacements
        String baseUrl = System.getenv("WEB_URL")
        
        baseUrl += baseUrl.endsWith("/") ? "" : "/"
        String url = baseUrl + "rest/buildlife/${buildLifeId}/tests?reportName=${name}"
        
        println "Sending request to $url"

        HttpPost postMethod = new HttpPost(url)
        if (authToken) {
            postMethod.addHeader("Authorization-Token", authToken)
            postMethod.addHeader("Content-Type", "application/xml")
        }
        
        println "Sending ${testCount} test results from ${suiteCount} test suites"
        postMethod.setEntity(new StringEntity(xml))
        
        HttpClientBuilder builder = new HttpClientBuilder()
        builder.setTrustAllCerts(true)
        HttpClient client = builder.buildClient()
        
        HttpResponse response = client.execute(postMethod)
        def responseCode = response.statusLine.statusCode
        InputStream responseStream = response.entity.content
        if (isGoodResponseCode(responseCode)) {
            IO.copy(responseStream, System.out)
            println ""
        }
        else {
            IO.copy(responseStream, System.err)
            throw new RuntimeException("Failed to upload MSTest test results. StatusCode: ${responseCode}")
        }
    }
    
    private boolean isGoodResponseCode(int responseCode) {
        return responseCode >= 200 && responseCode < 300;
    }
    
    private def encode = {
        return !it ? it : new java.net.URI(null, null, it, null).toASCIIString()
    }
}
