/*
* Licensed Materials - Property of IBM Corp.
* IBM UrbanCode Build
* IBM UrbanCode Deploy
* IBM UrbanCode Release
* IBM AnthillPro
* (c) Copyright IBM Corporation 2002, 2013. All Rights Reserved.
*
* U.S. Government Users Restricted Rights - Use, duplication or disclosure restricted by
* GSA ADP Schedule Contract with IBM Corp.
*/

import com.urbancode.air.AirPluginTool;

import groovy.io.FileType
import com.urbancode.ud.client.UDRestClient;
import com.urbancode.ud.client.ResourceClient;

import com.urbancode.air.XTrustProvider;

import com.urbancode.air.plugin.websphere.WebSphereCmdLineHelper;

XTrustProvider.install();

def apTool = new AirPluginTool(this.args[0], this.args[1]);
def props = apTool.getStepProperties();

def MAX_RETRIES = 3;

def weburl = System.getenv("AH_WEB_URL");
def user = apTool.getAuthTokenUsername();
def password = apTool.getAuthToken();
def finalURI = new URI(weburl);
def udClient = new ResourceClient(finalURI, user, password);

def rootResourcePath = props['resourcePath'];
def overridePath = props['pathOverride'];
def profilePathResource = props['profilePathResource'];
def profilePathAgent = props['profilePathAgent'];
def agent = props['agent'];
def roleName = "WebSphereCell";

// Setup variables
def wsadminPath = File.separator + "bin" + File.separator + WebSphereCmdLineHelper.getWSADMINValue();
def portdefsPath = File.separator + "properties" + File.separator + "portdef.props";

def getOrCreateSubResource = { resourcePath, parentUUID, description ->
	def resourceName = resourcePath.substring(resourcePath.lastIndexOf("/") + 1);
	def resource = null;
	def tries = 0;
	def done = false;
	while (!done && tries < MAX_RETRIES) {
		try {
			try {
				resource = udClient.getResourceByPath(resourcePath);
			}
			catch (IOException e) {
				//resource does not exist(i hope)
				resource = null;
			}
			if (resource == null) {
				def nodeId = udClient.createSubResource(parentUUID, resourceName, description);
				resource = udClient.getResourceByPath(resourcePath);
			}
			done = true;
		}
		catch (IOException e) {
			tries++;
			done = false;
			println("Got IOException in getOrCreateSubResource for ${resourcePath}");
			if (tries < MAX_RETRIES) {
				println ("Retrying...")
			}
			else {
				throw e;
			}
		}
	}

	return UUID.fromString(resource.getString("id"));
}

def addRoleToResource = { resource, role, properties ->
	def tries = 0;
	def done = false;
	while (!done && tries < MAX_RETRIES) {
		try {
			udClient.setRoleOnResource(resource.toString(), role, properties);
			done = true;
		} catch (IOException e) {
			tries++;
			done = false;
			println("Got IOException in addRoleToResource for ${resource}");
			if (tries < MAX_RETRIES) {
				println ("Retrying...")
			} else {
				throw e;
			}
		}
	}
}


def createProfileResource = { path ->
	println "";
	println "Processing: " + path;
	// clean up string if necessary
	if (path.endsWith(wsadminPath)) {
		path = path.replace(wsadminPath, "");
	}

	File file = new File(path);
	path = file.getAbsolutePath();
	// Check that the path exists
	if (!file.exists()) {
		println "Path does not exist...";
		return;
	}
	// check that wsadmin script exists
	File wsadmin = new File(path + wsadminPath);
	if (!file.exists()) {
		println "wsadmin script does not exist in the path...";
		return;
	}

	// check that portdef.propertiesexists
	File portdef = new File(path + portdefsPath);
	if (!portdef.exists()) {
		println "Path does not contain a base or ND profile..."
		return;
	}

	// get the SOAP port
	Properties portDefProps = new Properties();
	portDefProps.load(portdef.newDataInputStream());
	def soapPort = portDefProps.getProperty("SOAP_CONNECTOR_ADDRESS");
		
	println("Found WebSphere profile");
	println("SOAP port: " + soapPort);

	def cellProps = new HashMap<String, String>();

	File profileBin = new File(path + File.separator + "bin");
	def commandPath = profileBin.getAbsolutePath();
	cellProps.put("websphere.commandPath", commandPath + File.separator);
	cellProps.put("websphere.profilePath", path);
	cellProps.put("websphere.port", soapPort);

	// Do the creation in the server
	def rootResource = udClient.getResourceByPath(rootResourcePath);
	def rootResourceIdString = rootResource.getString("id");
	def rootResourceId = UUID.fromString(rootResourceIdString);

	def profileName = path.substring(path.lastIndexOf(File.separator) + 1);
	def resourcePath = rootResource.path + "/WebSphereCell - " + profileName;
	def description = "WebSphere Application Server cell for profile " + profileName;

	def cellResource = getOrCreateSubResource(resourcePath, rootResourceId, description);
	addRoleToResource(cellResource, "WebSphereCell", cellProps);
}

def paths = [];
if (profilePathResource != null && profilePathResource != "" && profilePathResource != '${p:resource/websphere.profilePath}') {
	paths.addAll(profilePathResource.tokenize(','));
}
if (profilePathAgent != null && profilePathAgent != "" && profilePathAgent != '${p:agent/websphere.profilePath}') {
	paths.addAll(profilePathAgent.tokenize(','));
}
if (paths.size() > 0) {
	// First check the profile paths from the resource. This should come from the top-level resource group, or the agent, property websphere.profilePath
	// It can be in the form of:
	// Single path - <path1>
	// Comma separated list - <path1>,<path2>,<path3>,<pathN>
	// Root profile path - <pathRoot1> (containing multiple profiles)
	// Combination - <pathRoot1>,<path2>,...<pathRootN>

	for (path in paths) {
		if (path.contains(wsadminPath)) {
			// path including wsadmin script
			createProfileResource(path);
		} else if (!new File(path + wsadminPath).exists()) {
			// Root profile path, so grab all base/dmgr profiles
			def profileRoot = new File(path);
			if (profileRoot.exists() && profileRoot.isDirectory()) {
				profileRoot.eachFile(FileType.DIRECTORIES) { file ->
					createProfileResource(file.getAbsolutePath());
				}
			} else {
				println "";
				println "Path is not a valid profile root: " + path;
			}
		} else {
			// Fully qualified profile path
			createProfileResource(path);
		}
	}
} else {
	// If there is no profile path from the resource, check the agent override, so we can still pick up one path
	// If there is no agent override, use the default path as normal
	def standardInstallPath = [];
	if (overridePath != null && overridePath != "" && overridePath != '${p:agent/wsadmin.path}') {
		if (!overridePath.endsWith(wsadminPath)) {
			overridePath += wsadminPath;
		}
		standardInstallPath << overridePath;

	}
	else if (apTool.isWindows) {
		standardInstallPath << "C:" + File.separator + "Program Files" + File.separator + "IBM" + File.separator + "WebSphere" + File.separator + "AppServer" + File.separator + "bin" + File.separator + "wsadmin.bat";
		standardInstallPath << "C:" + File.separator + "IBM" + File.separator + "WebSphere" + File.separator + "AppServer" + File.separator + "bin" + File.separator + "wsadmin.bat";
	}
	else {
		standardInstallPath << "/opt/IBM/WebSphere/AppServer/bin/wsadmin.sh";
	}

	def foundPath = "";
	for (path in standardInstallPath) {
		File file = new File(path);
		println "Checking path for WebSphere install: " + path;
		if (file.exists()) {
			foundPath = file.getAbsolutePath();
			break;
		}
	}

	if (foundPath) {
		def path = "";

		path = foundPath.substring(0, foundPath.lastIndexOf(File.separator)+1);
		apTool.setOutputProperty("roleName", roleName);
		apTool.setOutputProperty("websphere.commandPath", path);
		apTool.setOutputProperties();
		println "Found WebSphere install at " + path;
	}
	else {
		println "WebSphere installation not found. Ending discovery process.";
	}
}
