/* <copyright                                       */
/* notice="cics-lm-source-program"                  */
/* pids="CA0U"                                      */
/* years="2014"                                     */
/* crc="2663013135" >                               */
/* 	Licensed Materials - Property of IBM            */
/* 	CA0U                                            */
/* 	(C) Copyright IBM Corp. 2014 All Rights Reserved. */
/* 	US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */
/* </copyright>                                     */
package com.ibm.cics.ucd

import org.eclipse.core.runtime.IStatus
import org.eclipse.core.runtime.MultiStatus

import com.ibm.cics.core.model.CICSSystemManagerException
import com.ibm.cics.core.model.Context
import com.ibm.cics.core.model.ICPSM
import com.ibm.cics.core.model.ScopedContext
import com.ibm.cics.core.model.context.CPSMDefinitionPrimaryKey
import com.ibm.cics.core.model.internal.CICSResource
import com.ibm.cics.core.model.CICSObjectPrimaryKey
import com.ibm.cics.core.ui.ExceptionMessageHelper
import com.ibm.cics.model.ICICSDefinition
import com.ibm.cics.model.ICICSObject
import com.ibm.cics.model.ICICSType
import com.ibm.cics.model.IDefinition
import com.ibm.cics.sm.comm.ICICSAction
import com.ibm.cics.sm.comm.IContext
import com.ibm.cics.sm.comm.IFilteredContext
import com.ibm.cics.sm.comm.IPrimaryKey
import com.ibm.cics.sm.comm.IResourceErrorCode

import com.ibm.cics.sm.comm.ISystemManagerResponseValues
import com.ibm.cics.sm.comm.ISystemManagerReasonValues
import com.ibm.cics.sm.comm.IScopedContext
import com.ibm.cics.sm.comm.InstallException
import com.ibm.cics.sm.comm.SystemManagerActions
import com.ibm.cics.sm.comm.SystemManagerConnectionException
import com.ibm.cics.ucd.msg.CICSUCDMessage
import com.ibm.cics.ucd.steplabel.CICSUCDStepLabel

import static com.ibm.cics.model.AttributeValue.av;

import com.ibm.cics.core.model.AbstractCICSDefinitionType;

import java.text.MessageFormat

class CPSMHelper {

	// <copyright 
	// notice="cics-lm-java-class" 
	// pids="CA0U" 
	// years="2014" 
	// crc="3314407041" > 
	static final String COPYRIGHT = "Licensed Materials - Property of IBM CA0U (c) Copyright IBM Corp. 2014 All Rights Reserved. US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp."; //$NON-NLS-1$
	// </copyright> 

	//For newcopy and phasin in steps
	def performAction(ICPSM cpsm, ICICSAction cicsAction, ICICSType type, IContext context, String objectName) {
		try {
			cpsm.perform(context, type, cicsAction)
			System.out.println(MessageFormat.format(CICSUCDMessage.actionSucceedWithObjectName, cicsAction.getActionName(), objectName))
			return true
		} catch (CICSSystemManagerException e) {//this won't break step, but the step status will be failed
			SystemManagerConnectionException ex = (SystemManagerConnectionException) e.getCause();
			System.out.println(MessageFormat.format(CICSUCDMessage.actionFailWithObjectName, cicsAction.getActionName(), objectName))
			System.out.println(MessageFormat.format(CICSUCDMessage.commandFailDetailMsg, ex.getFunction(), ex.getResp1Name(), ex.getResp2()))
			return false
		}
	}
	//For newcopy and phasin in steps
	def perform(ICPSM cpsm, ICICSAction cicsAction, ICICSType type, IContext context, String objectName, int retryTimes, int retryInterval) throws Exception{
		ICICSObject[] objects = null
		try {
			objects = cpsm.getDefinitions2(type, context)
		} catch (CICSSystemManagerException e) {
			System.out.println(e.getMessage())
			throw new Exception(MessageFormat.format(CICSUCDMessage.checkScope, CICSUCDStepLabel.CICS_SCOPE, CICSUCDStepLabel.CICS_SCOPE))
		}

		boolean success = false
		if(objects == null || objects.length == 0) {
			System.out.println(MessageFormat.format(CICSUCDMessage.actionFailwithObjectNoFound, cicsAction.getActionName(), objectName))//this won't break step, but the step status will be failed
			return false
		}
		else {
			if(retryTimes > 0  &&  cicsAction.getActionName().equals(SystemManagerActions.NewCopy.getActionName())){//this is specific for NEWCOPY action
				while(retryTimes--) {
					success = performAction(cpsm, cicsAction, type, context, objectName)
					if (success)
						break
					else {
						if(retryTimes > 0) {
							System.out.println(MessageFormat.format(CICSUCDMessage.retrySecondLater, retryInterval))
							Thread.sleep(retryInterval*1000)
						}
					}
				}
			} else {
				success = performAction(cpsm, cicsAction, type, context, objectName)
			}
			return success
		}
	}

	//Use by install all CICS and CPSM resource, resource group etc.
	def installAction(ICPSM cpsm, IDefinition cicsDefinition, IScopedContext target, ICICSType type, String resourceName ) throws CICSSystemManagerException{

		cpsm.install(cicsDefinition, target)
		System.out.println(MessageFormat.format(CICSUCDMessage.actionSucceedWithObjectNameAndType,
				'Install', type.getResourceTableName(), resourceName))
		return true

	}

	//Used by Install Resource Description
	def performInstallResDescAction(ICPSM cpsm, ICICSAction cicsAction, ICICSType type,  IContext context, String objectName) throws CICSSystemManagerException{

		cpsm.perform(context, type, cicsAction)
		System.out.println(MessageFormat.format(CICSUCDMessage.actionSucceedWithObjectNameAndType,
				cicsAction.getActionName(), type.getResourceTableName(), objectName))
		return true

	}

	//PrimaryKey created with resource definition version, for DREP resource use
	def createPrimaryKeyForDrepResource(IContext context, String name, Long version){
		def key = new CICSObjectPrimaryKey(
				context,
				av(AbstractCICSDefinitionType.NAME, name),
				av(AbstractCICSDefinitionType.VERSION, version),
				av(AbstractCICSDefinitionType.CSDGROUP, ""))
		return key
	}

	//PrimaryKey created with CSD group, for CSD resource use
	def createPrimaryKeyForCsdResource(IContext context, String name, String csdGroup){
		def key = new CICSObjectPrimaryKey(context,
				av(AbstractCICSDefinitionType.NAME, name),
				av(AbstractCICSDefinitionType.VERSION, 0L),
				av(AbstractCICSDefinitionType.CSDGROUP, csdGroup))
		return key
	}

	//PrimaryKey created with CSD group/List, for group/list install
	def createPrimaryKeyForCsdGroupAndList(IContext context, String name){
		def key = new CICSObjectPrimaryKey(context,
				av(AbstractCICSDefinitionType.NAME, name))
		return key
	}

	//PrimaryKey created for CPSM resource type ( resource group , resource description)
	def createPrimaryKeyForCPSMResource(ICICSType type, IContext context, String name){
		def key = new CPSMDefinitionPrimaryKey(type, context, name)
		return key
	}

	//For step 'Install Resource form CSD'
	def installCSDResource(ICPSM cpsm,  ICICSType type, IContext context, String resourceName, String csdGroup) throws CICSSystemManagerException{

		boolean success = false
		ICICSDefinition definition = null
		def primaryKey = createPrimaryKeyForCsdResource(context, resourceName, csdGroup)
		definition = (ICICSDefinition) cpsm.get(type, primaryKey)
		success = installAction(cpsm, definition, context, type, resourceName)
		return success

	}

	//For step  'Install Resource form Data Repository'
	def installDREPResource(ICPSM cpsm,  ICICSType type, IScopedContext context, String resourceName, long version) throws CICSSystemManagerException{

		boolean success = false
		ICICSDefinition definition = null

		//For CPSM DREP install, the context for getting definition and target scope are not the same.
		//Getting CICS definition will only require a context with 'context' and scope null.
		//New a context from given FilteredContext
		IContext contextForDrepResource = new Context(context.getContext())
		def primaryKey = createPrimaryKeyForDrepResource(contextForDrepResource, resourceName, version)
		definition = (ICICSDefinition) cpsm.get(type, primaryKey)
		success = installAction(cpsm, definition ,new ScopedContext(context), type, resourceName)
		return success

	}

	//For step 'Install group or list from CSD'
	def installCSDGroupOrList(ICPSM cpsm,  ICICSType type, IScopedContext context, String groupOrListName) throws CICSSystemManagerException{

		boolean success = false
		IDefinition definition = null
		def primaryKey = createPrimaryKeyForCsdGroupAndList(context, groupOrListName)
		definition = (IDefinition) cpsm.get(type, primaryKey)
		success = installAction(cpsm, definition ,new ScopedContext(context), type, groupOrListName)
		return success

	}

	//For step 'Install resource group from CPSM DREP'
	def installDREPResourceGroup(ICPSM cpsm,  ICICSType type, IScopedContext context, String resourceGroupName) throws CICSSystemManagerException{

		boolean success = false
		IDefinition definition = null
		//For CPSM DREP install, the context for getting definition and target scope are not the same.
		//Getting CICS definition will only require a context with 'context' and scope null.
		//New a context from given FilteredContext
		IContext contextForDrepResource = new Context(context.getContext())
		def primaryKey = createPrimaryKeyForCPSMResource(type, contextForDrepResource, resourceGroupName)
		definition = (IDefinition) cpsm.get(type, primaryKey)
		success = installAction(cpsm, definition ,new ScopedContext(context), type, resourceGroupName)
		return success

	}

	//For step 'Install resource description from CPSM DREP'
	def installResDescription(ICPSM cpsm, ICICSType type, IContext context, ICICSAction cicsAction, String resourceDescName) throws CICSSystemManagerException{

		boolean success = false
		IContext contextForDrepResource = new Context(context.getContext())
		def primaryKey = createPrimaryKeyForCPSMResource(type, contextForDrepResource, resourceDescName)
		success = performInstallResDescAction(cpsm, cicsAction, type, primaryKey, resourceDescName)
		return success

	}

	// A method to handle all Install Exception
	def boolean handleInstallException(CICSSystemManagerException e, String resourceType, String resourceName) throws Exception{

		if(e.getMessage() == '0') {
			//CICS Explorer returns an Exception with the text '0' to indicate zero records were returned 
			System.out.println(MessageFormat.format(CICSUCDMessage.actionFailWithObjectNameAndType, CICSUCDMessage.install, resourceType, resourceName))
			System.out.println(MessageFormat.format(CICSUCDMessage.canNotFindResourceDefinition, resourceType, resourceName))
			return
		} else if (e.getCause() instanceof SystemManagerConnectionException) {
			SystemManagerConnectionException ex = (SystemManagerConnectionException) e.getCause();
			int responseCode = ex.getResponseCode();
			IResourceErrorCode errorCode = ex.getFeedbackErrorCode();
			int resp1 = ex.getResp1();
			String function = ex.getFunction();

			if (resp1 != 0){
				//Get the message when INSTALL action itself get failed, format the message. This fail should not stop STEP from executing
				//CNX0591E EXEC CICS command command RESP resp RESP2 resp2.
				System.out.println(MessageFormat.format(CICSUCDMessage.actionFailWithObjectNameAndType, CICSUCDMessage.install, resourceType, resourceName))
				System.out.println(MessageFormat.format(CICSUCDMessage.commandFailDetailMsg, ex.getFunction(), ex.getResp1Name(), ex.getResp2()))
				return

			} else if (errorCode != null && errorCode.getErrorCode() != 0) {
				//CNX0592E Attribute Name (attribute_name) Error (error)
				System.out.println(MessageFormat.format(CICSUCDMessage.actionFailWithObjectNameAndType, CICSUCDMessage.install, resourceType, resourceName))
				System.out.println(MessageFormat.format(CICSUCDMessage.cpsmCommandFailMsg, ex.getAttribute(), errorCode.getLabel()))
				return

			} else if (ex.getResponse() != ISystemManagerResponseValues.OK) {
				//CNX0593E RESPONSE (response) REASON (reason)
				if (ex.getResponse() == ISystemManagerResponseValues.INVALIDPARM && ex.getReason() == ISystemManagerReasonValues.SCOPE) {
					//'INVALIDPARM, SCOPE' reported in exception when the context and scope are not correct
					System.out.println(MessageFormat.format(CICSUCDMessage.checkContextAndScope,
							CICSUCDStepLabel.TARGET_SCOPE, CICSUCDStepLabel.CICSPLEX, CICSUCDStepLabel.TARGET_SCOPE))
					//Throw the exception as we need to stop STEP from execution in this situation
					throw ex
				}
				System.out.println(MessageFormat.format(CICSUCDMessage.actionFailWithObjectNameAndType, CICSUCDMessage.install, resourceType, resourceName))
				if(ex.getReason() == 0) {
					System.out.println(MessageFormat.format(CICSUCDMessage.actionFailMsgNoReason, ex.getResponseName()))
				} else {
					System.out.println(MessageFormat.format(CICSUCDMessage.actionFailMsg, ex.getResponseName(), ex.getReasonName()))
				}
				return
			} else {
				//Other unexpected CICSSystemManagerException caught
				System.out.println(MessageFormat.format(CICSUCDMessage.unexpectedException))
				throw ex
			}
		} else {
			//Other unexpected non-CICSSystemManagerException caught
			System.out.println(MessageFormat.format(CICSUCDMessage.unexpectedException))
			throw e
		}

	}











}
