/*
* 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.quality.cobertura

import org.apache.http.client.HttpClient
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 CoberturaCoverageXMLHelper {
    
    //**************************************************************************
    // CLASS
    //**************************************************************************

    //**************************************************************************
    // INSTANCE
    //**************************************************************************
    private def testCount = 0
    private def suiteCount = 0
    
    public CoberturaCoverageXMLHelper() {
    }
    
    def uploadResult (reportName, buildLifeId, coverageXmlFile) {
        def testsuiteName
        def xml
        def result
        def name
        def time
        testCount = 0
        suiteCount = 0
        
        /*
        <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        
             <xsd:complexType name="CoverageReport">
                 <xsd:sequence>
                     <xsd:element name="coverage-group" type="CoverageGroup" minOccurs="0" maxOccurs="unbounded"/>
                 </xsd:sequence>
                 <xsd:attribute name="name" type="xsd:string" use="required"/>
                 <xsd:attribute name="type" type="xsd:string" use="required"/>
                 <xsd:attribute name="line-percentage" type="xsd:double" use="optional"/>
                 <xsd:attribute name="method-percentage" type="xsd:double" use="optional"/>
                 <xsd:attribute name="branch-percentage" type="xsd:double" use="optional"/>
             </xsd:complexType>
        
             <xsd:complexType name="CoverageGroup">
                 <xsd:attribute name="name" type="xsd:string" use="required"/>
                 <xsd:attribute name="line-percentage" type="xsd:double" use="optional"/>
                 <xsd:attribute name="method-percentage" type="xsd:double" use="optional"/>
                 <xsd:attribute name="branch-percentage" type="xsd:double" use="optional"/>
                 <xsd:attribute name="complexity" type="xsd:double" use="optional"/>
             </xsd:complexType>
        
             <xsd:element name="coverage-report" type="CoverageReport"/>
        
         </xsd:schema>
         */

        XmlParser parser = new XmlParser()
        parser.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
        parser.setFeature("http://xml.org/sax/features/namespaces", false)
        def rootNode = parser.parse(coverageXmlFile)
        
        def reportXml = new java.io.StringWriter()
        new groovy.xml.MarkupBuilder(reportXml).
            "coverage-report"(
                "name": reportName,
                "type": 'Cobertura',
                "build-life-id": buildLifeId,
                "line-percentage": rootNode.@"line-rate",
                "method-percentage": "0",
                "branch-percentage": rootNode.@"branch-rate",
                "complexity": rootNode.@complexity
            ) {
            rootNode.packages."package".each { packageNode ->
                "coverage-group"(
                    "name": packageNode.@name,
                    "line-percentage": packageNode.@"line-rate",
                    "method-percentage": "0",
                    "branch-percentage": packageNode.@"branch-rate",
                    "complexity": packageNode.@complexity
                )
            }
        }
            
        if (reportXml) {
            //println "Sending report:\n" + reportXml.toString()
            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}/testcoverage?reportName=${name}"
        
        println "Sending request to $url"

        HttpClientBuilder clientBuilder = new HttpClientBuilder();
        clientBuilder.setTrustAllCerts(true);
        DefaultHttpClient client = clientBuilder.buildClient();
        
        HttpPost postMethod = new HttpPost(url);
        if (authToken) {
            postMethod.setHeader("Authorization-Token", authToken)
            postMethod.setHeader("Content-Type", "application/xml")
        }
       
        postMethod.setEntity(new StringEntity(xml));
    
        def httpResponse = client.execute(postMethod)
        def responseCode = httpResponse.getStatusLine().getStatusCode()
        if (isGoodResponseCode(responseCode)) {
            IO.copy(postMethod.getEntity().getContent(), System.out)
            println ""
        }
        else {
            IO.copy(postMethod.getEntity().getContent(), System.err)
            throw new RuntimeException("Failed to upload Cobertura coverage report. 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()
    }
}