package com.urbancode.air.plugin.maximo


import org.apache.http.HttpResponse

/**
 * (c) Copyright IBM Corporation 2016, 2017.
 * (c) Copyright HCL Technologies Ltd. 2018, 2019. All Rights Reserved.
 * This is licensed under the following license.
 * The Eclipse Public 1.0 License (http://www.eclipse.org/legal/epl-v10.html)
 * U.S. Government Users Restricted Rights:  Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
 */

import groovy.json.JsonSlurper
import java.text.SimpleDateFormat
import java.util.Properties
import org.apache.http.HttpResponse
import org.apache.http.HttpStatus
import org.apache.http.util.EntityUtils
import org.apache.log4j.Logger
import org.codehaus.jettison.json.JSONArray
import org.codehaus.jettison.json.JSONObject
import java.net.URL
import java.net.URLEncoder

class MaximoRestClient {

	private RestClientHelper restHelper
	private Logger logger

	private String host
	private String port
	private String serverUrl
	private String userName
	private String password
	private String apiKey;
	private String fileName;
	private String filePath;
	private Properties props;


	public MaximoRestClient(Properties props) {
		
		this.props = props;

		// Local fields
		this.host = props['host'].toString().trim()
		this.userName = props['userName'].toString().trim()
		this.password = props['password'].toString()
		this.apiKey = props['apiKey'].toString()


		if (props['port']) {
			this.port = props['port'].toString().trim()
		}

		/* Default to http unless otherwise specified */
		if (!this.host.startsWith("http://") && !host.startsWith("https://")) {
			this.host = "https://" + this.host;
		}

		logger = Logger.getLogger(getClass())

		if (this.host) {

			this.serverUrl = this.host

			if(this.port ) {
				this.serverUrl += ":" + this.port
			}

			this.serverUrl += "/maximo/api"

			println("${getTimestamp()} Establishing connection with a maximo server...")

			restHelper = new RestClientHelper(this.serverUrl, this.userName, this.password, this.apiKey,  true)

		}else {
			throw new IllegalStateException("Must specify either an 'IP' and 'Port'.")
		}

		println("${getTimestamp()} Maximo connection successful.")
	}

	public void uploadPackage() {

		Date startTime = new Date()
		HttpResponse response;		
		
		this.filePath = props['filePath'].toString().trim()
		
		try {
			
			File zipFile = new File(this.filePath);
			this.fileName = zipFile.getName()
			
			String uploadUrl = this.serverUrl + "/" + "dm/upload?filename=" + this.fileName

			
			
			response = restHelper.doPostRequest(uploadUrl, zipFile, this.fileName);

			if (!response.getStatusLine().getStatusCode().equals(HttpStatus.SC_OK)) {
				println ("[Error] Bad response code of ${response.getStatusLine().getStatusCode()} - ${response}.")
				println ('Response:\n' + response.entity?.content?.getText("UTF-8"))
				throw new Exception()
			}

		}catch (Exception ex) {
			ex.printStackTrace()
			throw ex
		}

		System.out.println("${getTimestamp()} Successfully uploaded package.")

	}


	public void deployPackage() {

		Date startTime = new Date()
		HttpResponse response;
		Map<String, String> responseJson = new HashMap<String, String>()
		
		String initialAdminMode = getAdminModeState();

		try {

			String deployUrl = this.serverUrl + "/" + "dm/deploy"

			println ("Current admin mode state :" + initialAdminMode)
			
			if(!getAdminModeState().equals("on")) {
			
				setAdminModeState("on")
			}
			
			response = restHelper.doPostRequest(deployUrl)

			if (!response.getStatusLine().getStatusCode().equals(HttpStatus.SC_OK)) {
				println ("[Error] Bad response code of ${response.getStatusLine().getStatusCode()} - ${response}.")
				println ('Response:\n' + response.entity?.content?.getText("UTF-8"))
				throw new Exception()
			}

			if(response) {
				
				responseJson = restHelper.parseResponse(response)
				String warningmsg = responseJson.get("warningmsg")
				println (warningmsg);
				
			}
			
		}catch (Exception ex) {
			ex.printStackTrace()
			throw ex
		}

		if(!initialAdminMode.equals(getAdminModeState())) {
			setAdminModeState(initialAdminMode)
			println ("Switching back to admin mode state which was before deploy to  :" + initialAdminMode)
		}
	}

	public void cleanUp() {
		//TODO

	}
	
	public String getAdminModeState() {
		
		String status="";
		
		Date startTime = new Date()
		HttpResponse response;
		Map<String, String> responseJson = new HashMap<String, String>()
		
		try {

			String adminModeUrl = this.serverUrl + "/" + "adminmode/state"


			response = restHelper.doGetRequest(adminModeUrl)


			if (!response.getStatusLine().getStatusCode().equals(HttpStatus.SC_OK)) {
				println ("[Error] Bad response code of ${response.getStatusLine().getStatusCode()} - ${response}.")
				println ('Response:\n' + response.entity?.content?.getText("UTF-8"))
				throw new Exception()
			}

			if(response) {
				
				responseJson = restHelper.parseResponse(response)
				status = responseJson.get("state").toString()
				
			}
			
		}catch (Exception ex) {
			ex.printStackTrace()
			throw ex
		}
	
		switch(status) {
			
			case "0" :status = "off";
					  break;
			case "1" :status = "on";
					  break;
			case "2" :status = "pending";
					  break;	  
		}
		
		return status;
	}
	
	void setAdminModeState(String state) {
		

		JSONObject postData = new JSONObject();
		postData.put("numsessions", 5);
		postData.put("logoutmin", 20);

		String status="";
		
		Date startTime = new Date()
		HttpResponse response;

		try {

			String adminModeSetUrl = this.serverUrl + "/" + "adminmode/"+state

			println ("Setting admin mode state to : " + state)
			
			if(state.equals("on")) {
				response = restHelper.doPostRequest(adminModeSetUrl, postData.toString())
			}else {
				response = restHelper.doPostRequest(adminModeSetUrl)
			}


			if (!response.getStatusLine().getStatusCode().equals(HttpStatus.SC_OK)) {
				println ("[Error] Bad response code of ${response.getStatusLine().getStatusCode()} - ${response}.")
				println ('Response:\n' + response.entity?.content?.getText("UTF-8"))
				throw new Exception()
			}

			
		}catch (Exception ex) {
			ex.printStackTrace()
			throw ex
		}
		
		while(!getAdminModeState().equals(state)) {
		
			println ("Checking admin mode state  : " + getAdminModeState())
			println ("Will check in next 10 seconds")
			Thread.sleep(10 * 1000)
		}
		
		println ("Admin mode state set to mode : " + state)
		
	}


	public static String getTimestamp() {
		SimpleDateFormat dateFormat = new SimpleDateFormat("[MM/dd/yyyy HH:mm:ss]")

		return dateFormat.format(new Date())
	}

	/**
	 * Encode HTML form parameters.
	 * @param path
	 * @return The encoded parameter.
	 * @throws UnsupportedEncodingException
	 */
	private String encodePath(String path) throws UnsupportedEncodingException {
		return URLEncoder.encode(path, "UTF-8");
	}



}
