/*
* Licensed Materials - Property of IBM* and/or HCL**
* UrbanCode Deploy
* (c) Copyright IBM Corporation 2013, 2017. All Rights Reserved.
* (c) Copyright HCL Technologies Ltd. 2018. All Rights Reserved.
*
* U.S. Government Users Restricted Rights - Use, duplication or disclosure restricted by
* GSA ADP Schedule Contract with IBM Corp.
*
* * Trademark of International Business Machines
* ** Trademark of HCL Technologies Limited
*/
package com.urbancode.air.plugin.webutilities

import org.apache.http.client.methods.CloseableHttpResponse
import org.apache.http.client.methods.HttpUriRequest
import org.apache.http.impl.client.CloseableHttpClient

import groovy.transform.Field

import com.urbancode.air.AirPluginTool
import com.urbancode.air.plugin.webutilities.BuildClient
import com.urbancode.air.plugin.webutilities.CreateHTTPRequest
import com.urbancode.air.plugin.webutilities.HTTPResponseProcessing
import com.urbancode.air.plugin.webutilities.TextAreaToHashMap
import com.urbancode.air.plugin.webutilities.ValidateEncodeURL

AirPluginTool apTool = new AirPluginTool(this.args[0], this.args[1])

Properties inProps = apTool.getStepProperties()

@Field
Properties outProps = new Properties()

try {
    executeHTTP(inProps)
    Integer status = Integer.parseInt(outProps['responseStatus'])
    if (status > 399) {
        throw new Exception('Status returned indicates server received and processed request successfully, but could not do what was asked.')
    }
} finally {
    if (outProps) {
        Enumeration e = outProps.propertyNames()
        while (e.hasMoreElements()) {
            String key = (String) e.nextElement()
            apTool.setOutputProperty(key, outProps.getProperty(key))
        }
        apTool.setOutputProperties()
    }
}

// Main Method
public void executeHTTP (Properties inProps) {
    println "[action] Building and validating request."

    // Trim appropriate user inputs
    Boolean preemptiveAuthentication = Boolean.valueOf(true)
    Boolean untrustedSSL = Boolean.valueOf(inProps['untrustedSSL'])

    // Set base HTTP request settings
    CloseableHttpClient client = BuildClient.buildHTTPClient(inProps['password'],
        preemptiveAuthentication,
        "",
        "",
        null,
        "",
        untrustedSSL,
        inProps['username'])

    // validates and encodes the url
    String url
    try {
        url = ValidateEncodeURL.encodeURL(inProps['url'])
    } catch (MalformedURLException e) {
        print(e.getMessage())
        throw e
    }

    // Parses inputted headers
    Map headerMap = ["Content-Type":inProps['contentType'],"accept":inProps['acceptType']]
    headerMap = TextAreaToHashMap.textAreaToHashMap(inProps['headers'], headerMap)

    // Get body data from text or file
    String data = inProps['data']
    HttpUriRequest httpRequestEntity

    if(inProps['contentType'] == "application/zip") {
        File infile = new File(data)
        if (infile.exists() && !infile.isDirectory()) {
            // Formulates the complete HTTP request
            httpRequestEntity = CreateHTTPRequest.createHTTPRequestForZip(url,
                headerMap, inProps['method'], infile)
        }else {
            throw new Exception ('A valid file name must be provided for request content type ZIP archive. ')
        }
    }else {

        try {
            File infile = new File(data)
            if (infile.exists() && !infile.isDirectory()) {
                      println "[action] Reading body from file. "
                    data = infile.getText()
            }
            else {
                println "[action] Reading body from text box."
            }
        } catch (NullPointerException e) {
            println "[info] Message body is blank."
        }

        // Formulates the complete HTTP request
        httpRequestEntity = CreateHTTPRequest.createHTTPRequest(url,
            headerMap, inProps['method'], data)
    }

    // Send Request
    CloseableHttpResponse response
    try {
        println "[action] Executing request."
        response = client.execute(httpRequestEntity)
    } catch (ConnectException e) {
        println "[error] Connection refused: There is no service listening on the port. Please check that:"
        println "1. The recieving service is up."
        println "2. The host name or ip address is correct."
        println "3. The port number is correct."
        throw e
    } catch (Exception e) {
        e.printStackTrace()
        throw e
    }

    // Process response
    File outFile = null
    if (inProps['outFile']) {
        File workDir = new File(".").getCanonicalFile()
        outFile = new File(workDir, inProps['outFile'])
        println "[action] Response body written to file ${outFile.getAbsolutePath()}"
    }

    println "[action] Processing response."
    this.outProps = HTTPResponseProcessing.hTTPResponseProcessing(response, outFile, this.outProps)
}
