/*
 * Licensed Materials - Property of IBM* and/or HCL**
 * IBM UrbanCode Build
 * IBM UrbanCode Deploy
 * IBM UrbanCode Release
 * IBM AnthillPro
 * (c) Copyright IBM Corporation 2002, 2015. 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
 */
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeSocketFactory;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy

import groovyx.net.http.RESTClient
import groovyx.net.http.AuthConfig
import groovyx.net.http.ContentType
import groovyx.net.http.HttpResponseException

import com.urbancode.air.AirPluginTool


try{
	def apTool = new AirPluginTool(this.args[0], this.args[1])
	final def workDir = new File('.').canonicalFile
	def props = apTool.getStepProperties();

	final def workflowName = props['workflowName']?.trim();
	final def workflowDefinitionFile = props['workflowDefinitionFile']?.trim();
	final def system = props['system']?.trim();
	final def owner = props['owner']?.trim();
	final def assignToOwner = Boolean.valueOf(props['assignToOwner']?.trim());  //checkbox
	final def jobStatement = props['jobStatement']?.trim();
	final def comments = props['comments']?.trim();
	final def variableInputFile = props['variableInputFile']?.trim();
	final def variables = props['variables']?.trim();
	final def resolveGlobalConflictByUsing = props['resolveGlobalConflictByUsing']?.trim();
	final def printRESTLOG = Boolean.valueOf(props['printRESTLOG']?.trim()); //checkbox
	final def generateUniqueName = Boolean.valueOf(props['generateUniqueName']?.trim()); //checkbox

	//hidden
	final def baseurl = props['baseurl']?.trim();
	final def untrustedSSL = Boolean.valueOf(props['untrustedSSL']?.trim()); //checkbox
	final def userid = props['userid']?.trim();
	final def password = props['password']?.trim();

	//validate required input
	if(workflowName == null || workflowName.length()==0){
		throw new Exception("Workflow Name must be set.");
	}

	if(workflowDefinitionFile == null || workflowDefinitionFile.length()==0){
		throw new Exception("Workflow Definition File must be set.");
	}

	if(system == null || system.length()==0){
		throw new Exception("System must be set.");
	}

	if(owner == null || owner.length()==0){
		throw new Exception("Owner must be set.");
	}

	if(baseurl == null || baseurl.length()==0){
		throw new Exception("zOSMF URL must be set.");
	}

	if(userid == null || userid.length()==0){
		throw new Exception("User Name must be set.");
	}

	if(password == null || password.trim().length()==0){
		throw new Exception("Password must be set.");
	}

	def create_workflow_path="/zosmf/workflow/rest/1.0/workflows/"
	def client = new RESTClient(baseurl)
	client.contentType = ContentType.JSON  //zosmf API uses JSON
	client.encoder.setCharset("UTF-8")  //do not use default encoding
	client.auth.basic userid, password
    client.headers['X-CSRF-ZOSMF-HEADER']="UCD";
    
	if(untrustedSSL){
		//allow untrustedSSL
		TrustStrategy trustStrat = new TrustStrategy(){
					public boolean isTrusted(X509Certificate[] chain, String authtype)
					throws CertificateException {
						return true;
					}
				};
		SchemeSocketFactory schemeSocketFactory = new SSLSocketFactory(trustStrat,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
		Scheme scheme = new Scheme("https",  443, schemeSocketFactory);
		client.client.connectionManager.schemeRegistry.register(scheme);
	}


	//prepare JSON request
	if(generateUniqueName){
		workflowName = workflowName + " - " + Calendar.instance.time.time
		println "Creating workflow : ${workflowName}"
	}
	apTool.setOutputProperty("zosmf.workflowName", workflowName);
	apTool.storeOutputProperties();

	def body = 	[      workflowName : workflowName,
		workflowDefinitionFile : workflowDefinitionFile,
		system : system,
		owner : owner,
		assignToOwner : assignToOwner  ]

	//add optional fields
	if(comments) 			body << [comments : comments]
	if(variableInputFile) 	body << [variableInputFile : variableInputFile]
	if(resolveGlobalConflictByUsing) body << [resolveGlobalConflictByUsing : resolveGlobalConflictByUsing]
	if(variables){
		def vJSON = []
		def vProp =new Properties()
		vProp.load(new StringReader(variables))
		vProp.each{key,value->
			vJSON.add(["name":key,"value":value])
		}
		body << [variables : vJSON]
	} 			
	if(jobStatement) 			body << [jobStatement : jobStatement]
	if(printRESTLOG) {
		println "Create workflow request body:"
		println body
		println ""
	}

	try{
		def resp  = client.post(
				path : create_workflow_path,
				body : body,
				requestContentType: ContentType.JSON
				)
		if(printRESTLOG) {
			println "Create workflow response status line:"
			println resp.statusLine
			println ""
			println "Create workflow response body:"
			println resp.data ? resp.data : ""
			println ""
		}

		//Based on zOSMF Create Workflow REST API
		//On successful completion, HTTP status code 201 (Created) is returned and the response body is provided
		if(resp.status == 201){ //Created
			println "Workflow created. "
			resp.data.each {
				println it.key + " : " + it.value
				apTool.setOutputProperty("zosmf." + it.key, it.value);
			}
			apTool.storeOutputProperties();
			System.exit(0);
		}else if(resp.status == 200){
			//The request succeeded. A response body is provided, which contains the results of the request
			//typically means an failure in creating workflow
			println "Workflow was not created. "
			resp.data.each {
				println it.key + " : " + it.value
			}
			System.exit(1)
		}else{
			println "Unknow response code. "
			System.exit(1)
		}

	}catch (HttpResponseException e){
		//any HTTP status code > 399 will end up here.

		if(printRESTLOG) {
			println "Create workflow response status line:"
			println e.response.statusLine
			println ""
			println "Create workflow response body:"
			println e.response.data? e.response.data : ""
			println ""
		}
		//HTTP 400 Bad request
		//HTTP 403 Forbidden
		println "Failed to create workflow."
		e.response.data.each {
			println it.key + " : " + it.value
		}

		if(e.response.status==401){
			println "Incorrect user ID or password, or both."
		}
		System.exit(1)
	}

}catch (Exception e) {
	println "Error creating workflow : ${e.message}";
	e.printStackTrace();
	System.exit(1);
}