/*
* 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.reportpublisher;

import java.nio.charset.Charset
import java.nio.charset.spi.CharsetProvider

import org.apache.http.HttpResponse
import org.apache.http.client.HttpClient
import org.apache.http.client.methods.HttpPost
import org.apache.http.entity.ContentType
import org.apache.http.entity.mime.HttpMultipartMode
import org.apache.http.entity.mime.MultipartEntity
import org.apache.http.entity.mime.content.FileBody
import org.apache.http.entity.mime.content.StringBody

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

public class UploadHelper {
    
    //**************************************************************************
    // CLASS
    //**************************************************************************
    
    final def boundary = "---------------8jujieu8479wueire584w9en";

    //**************************************************************************
    // INSTANCE
    //**************************************************************************
    private File sourceDir = null;
    
    public UploadHelper(sourceDir) {
        this.sourceDir = sourceDir
    }
    
    def uploadResult (reportFiles, reportName, jobId) {
        if (!reportFiles) {
            println 'No report was able to be generated'
            return;
        }
        if (reportName == null || reportName.isEmpty()) {
            throw new NullPointerException("Report name must be provided");
        }
        if (jobId == null || jobId.isEmpty()) {
            throw new NullPointerException("A job ID must be provided");
        }

        sendPostRequest(reportName, (File[]) reportFiles.toArray(), jobId)
    }

    private void sendPostRequest(String name, File[] reportFiles, String jobId) {
        def authToken = System.getenv("AUTH_TOKEN")
        String buildLifeId = System.getenv("BUILD_LIFE_ID")
        def reportName = URLEncoder.encode(name)

        // construct the URL with property replacements
        String baseUrl = System.getenv("WEB_URL")

        baseUrl += baseUrl.endsWith("/") ? "" : "/"
        String url = baseUrl + "rest/buildlife/${buildLifeId}/publishedReports"

        println "Sending request to $url"

        HttpPost postMethod = new HttpPost(url)
        if (authToken) {
            postMethod.addHeader("Authorization-Token", authToken)
            postMethod.addHeader("Content-Type", "multipart/mixed;boundary=${boundary}")
        }
        
        println "Uploading ${reportFiles.length} files in report \"${name}\" to build life ${buildLifeId}"
        
        Charset utf8 = Charset.forName("UTF-8")
        def multipartEntity = new MultipartEntity(HttpMultipartMode.STRICT, boundary, utf8)
        multipartEntity.addPart("reportName", new StringBody(reportName, utf8))
        multipartEntity.addPart("pathSeparator", new StringBody(File.separator, utf8))
        multipartEntity.addPart("jobId", new StringBody(jobId, utf8))

        def i = 0;
        reportFiles.each { reportFile ->
            String uniqueFieldName = "file${i}";
            String filePath = FileUtils.getRelativeFileName(sourceDir, reportFile)
            filePath = filePath.replace(File.separator, '/')
            FileBody fileBody = new FileBody(reportFile, filePath, "application/octet-stream", "UTF-8") 
            multipartEntity.addPart(uniqueFieldName, fileBody);
            i++;
        }
        postMethod.setEntity(multipartEntity);
        
        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 "Successfully uploaded all files"
        }
        else {
            IO.copy(responseStream, System.err)
            throw new RuntimeException("Failed to upload reports. StatusCode: ${responseCode}")
        }
    }

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