/*
* Licensed Materials - Property of IBM Corp.
* IBM UrbanCode Build
* IBM UrbanCode Deploy
* IBM UrbanCode Release
* IBM AnthillPro
* (c) Copyright IBM Corporation 2002, 2016. 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.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 sever received and processd 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 validatating 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 = ["contenttype":inProps['contentType'],"accept":inProps['contentType']]
    headerMap = TextAreaToHashMap.textAreaToHashMap(inProps['headers'], headerMap)

    // Get body data from text or file
    String data = inProps['data']
    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
    HttpUriRequest 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)
}
