package org.eclipse.papyrus.designer.components.transformation.cpp.xtend

import java.util.List
import org.eclipse.emf.common.util.BasicEList
import org.eclipse.emf.ecore.util.EcoreUtil
import org.eclipse.papyrus.designer.components.transformation.component.PrefixConstants
import org.eclipse.papyrus.designer.languages.common.base.ElementUtils
import org.eclipse.papyrus.designer.languages.common.profile.Codegen.TemplateBinding
import org.eclipse.papyrus.designer.languages.cpp.library.CppUriConstants
import org.eclipse.papyrus.designer.transformation.core.transformations.LazyCopier
import org.eclipse.papyrus.uml.tools.utils.PackageUtil
import org.eclipse.papyrus.uml.tools.utils.StereotypeUtil
import org.eclipse.uml2.uml.AggregationKind
import org.eclipse.uml2.uml.BehavioredClassifier
import org.eclipse.uml2.uml.Class
import org.eclipse.uml2.uml.ConnectorEnd
import org.eclipse.uml2.uml.Interface
import org.eclipse.uml2.uml.LiteralString
import org.eclipse.uml2.uml.OpaqueBehavior
import org.eclipse.uml2.uml.ParameterDirectionKind
import org.eclipse.uml2.uml.Port
import org.eclipse.uml2.uml.Property
import org.eclipse.uml2.uml.Type
import org.eclipse.uml2.uml.UMLPackage

/**
 * Enable ports that delegate to several inner parts/ports, see bug 531771
 * 
 * This delegation is bidirectional, i.e. applies to provided and required
 * ports (methods being called and methods that are calling, respectively)
 * 
 * For provided ports: return the reference to a broadcast class in the
 *   get_XXX methods.
 *   The user has to verify that the port of the composite has the right
 *   multiplicity.
 * 
 * For required ports: call all connect_XXX of inner parts in the connect_XXX
 *   of the class that owns inner parts.
 * 
 * Finally the createConnection method should handle connecting to a port that
 * returns a vector. In this case we expect the receptacle of the connection
 * to be of multiplicity several.
 */
class CreateMultiRefClass {

	StaticCppToOO cppToOO
	LazyCopier copier
	static String progLang = "C++"

	new(StaticCppToOO cppToOO, LazyCopier copier) {
		this.cppToOO = cppToOO
		this.copier = copier
	}

	def String createDelegationProvided(Class implementation, List<ConnectorEnd> ces, Port port, String portName,
		Interface providedIntf) {

		// We need to create a port representing the delegating port
		val attributeName = PrefixConstants.attributePrefix + portName

		var attr = implementation.getOwnedAttribute(attributeName, null)
		if (attr === null || attr instanceof Port) {
			val broadcastClass = getOrCreateBroadcastClass(providedIntf)

			// Create the attribute in implementation for the port and type it with the broadcast class
			attr = implementation.createOwnedAttribute(attributeName, broadcastClass)
			val defaultValue = attr.createDefaultValue("default", attr.type, UMLPackage.Literals.LITERAL_STRING) as LiteralString
			defaultValue.value = "NULL";
			attr.setAggregation(AggregationKind.SHARED_LITERAL)

			// Connect delegated parts (either properties or ports) to the broadcast class
			return createDelegationConnCode(ces, broadcastClass, portName, providedIntf)
		}
		return ""
	}

	def String createDelegationConnCode(List<ConnectorEnd> ces, Class broadcastClass, String portName,
		Interface providedIntf) '''
		«val attributeName = PrefixConstants.attributePrefix + portName»
		// generated broadcast class uses generic port name
		«val connectOpName = PrefixConstants.connectQ_Prefix + "port"»
		
		if («attributeName» == NULL) {
			«attributeName» = new «broadcastClass.qualifiedName»();
		}
		
		«FOR ce : ces»
			«val part = ce.partWithPort»
			«val role = ce.role»
			
			«IF role instanceof Port»
				«val rolePort = role as Port»
				«IF rolePort.provideds.contains(providedIntf)»
					«IF rolePort.provideds.size > 1 ||
								((rolePort.provideds.size == 1) && !(rolePort.type instanceof Interface))»
						«IF part.upper > 1»
							«FOR i : 0 ..< part.upper»
								«attributeName»->«connectOpName»(«part.name»[«i»].«PrefixConstants.getP_Prefix»«role.name»«providedIntf.name»());
							«ENDFOR»
						«ELSE»
							«attributeName»->«connectOpName»(«cppToOO.nameRef(part)»«PrefixConstants.getP_Prefix»«role.name»«providedIntf.name»());
						«ENDIF»
					«ELSE»
						«IF part.upper > 1»
							«FOR i : 0 ..< part.upper»
								«attributeName»->«connectOpName»(«part.name»[«i»].«PrefixConstants.getP_Prefix»«role.name»());
							«ENDFOR»
						«ELSE»
							«attributeName»->«connectOpName»(«cppToOO.nameRef(part)»«PrefixConstants.getP_Prefix»«role.name»());
						«ENDIF»
					«ENDIF»
				«ENDIF»
			«ELSE»
				«IF role instanceof Property»
					«val roleType = (role as Property).type»
					«IF roleType instanceof BehavioredClassifier &&
								(roleType as BehavioredClassifier).getInterfaceRealization(null, providedIntf) !== null»
						«IF (role as Property).upper > 1»
							«FOR i : 0 ..< (role as Property).upper»
								«attributeName»->«connectOpName»(«role.name»[«i»]);
							«ENDFOR»
						«ELSE»
							«attributeName»->«connectOpName»(«role.name»);
						«ENDIF»
					«ENDIF»
				«ENDIF»
			«ENDIF»
		«ENDFOR»
		
		return «attributeName»;
	'''

	def String createDelegationRequired(Class implementation, String portName, Interface requiredIntf) {

		val attributeName = PrefixConstants.attributePrefix + portName
		// generated broadcast class uses generic port name
		val opName = PrefixConstants.connectQ_Prefix + "port"
		
		// We need to create a port representing the delegating port
		var attr = implementation.getOwnedAttribute(attributeName, null)
		if (attr === null || attr instanceof Port) {

			val broadcastClass = getOrCreateBroadcastClass(requiredIntf)
			// Create the attribute in implementation for the port and type it with the broadcast class
			attr = implementation.createOwnedAttribute(attributeName, broadcastClass)
			val defaultValue = attr.createDefaultValue("default", attr.type, UMLPackage.Literals.LITERAL_STRING) as LiteralString
			defaultValue.value = "NULL";
			cppToOO.applyRef(attr);
			// CopyUtils.copyMultElemModifiers(port, attr)
			// Delegate reference management to broadcastCass
			return '''
				if (!«attributeName») {
					«attributeName» = new «broadcastClass.qualifiedName»();
				}
				«attributeName»->«opName»(ref);
			'''
		}
		return "";
	}

	/**
	 * Create a new broadcast class or create an existing
	 */
	def Class getOrCreateBroadcastClass(Interface intf) {
		val broadcastClassName = '''Broadcast_«intf.name»'''
		var broadcastClass = intf.nearestPackage.getPackagedElement(broadcastClassName)
		if (broadcastClass instanceof Class) {
			return broadcastClass as Class
		} else {
			return createBroadcastClass(intf)
		}
	}

	/**
	 * Create a broadcast class for a given interface. This class will manage multiple references for the
	 * given interface and provide an API for calling each method of the interface.
	 * The called operation is called for each stored reference. If there is a return value, only the
	 * return value of the last call is returned.
	 */
	def Class createBroadcastClass(Interface intf) {
		// Create the broadcast class
		// use generic name port, since the implementation is not specific to the port using it
		val opName = PrefixConstants.connectQ_Prefix + "port"
		val broadcastClassName = '''Broadcast_«intf.name»'''
		val broadcastClass = intf.nearestPackage.createOwnedClass(broadcastClassName, false)

		// Set its interface realization
		broadcastClass.createInterfaceRealization("broadcast" + intf, intf)

		// Create the references vector (based on std::vector from STL)
		PackageUtil.loadPackage(CppUriConstants.STL_LIB_URI, copier.source.eResource.resourceSet)
		
		var vector = ElementUtils.getQualifiedElementFromRS(copier.source, PrefixConstants.TYPE_FOR_MULTI_RECEPTACLE) as Type;
		if (vector !== null) {
			vector = copier.getCopy(vector);
		} else {
			throw new RuntimeException(
				String.format(
					"Can not find type %s. Thus, unable to create suitable connect operation in component to OO transformation",
					PrefixConstants.TYPE_FOR_MULTI_RECEPTACLE));
		}
		var references = broadcastClass.createOwnedAttribute("references", vector)
		val tBinding = StereotypeUtil.applyApp(references, TemplateBinding)
		tBinding.actuals.add(cppToOO.createPtrType(intf))

		// Create the connect method
		val connectOperation = broadcastClass.createOwnedOperation(opName, null, null)
		val connectRefParam = connectOperation.createOwnedParameter("ref", intf)
		cppToOO.applyRef(connectRefParam)
		val connectBehavior = broadcastClass.createOwnedBehavior(opName,
			UMLPackage.eINSTANCE.getOpaqueBehavior()) as OpaqueBehavior
		connectOperation.getMethods().add(connectBehavior)
		connectBehavior.getLanguages().add(progLang)
		connectBehavior.getBodies.add(
			'''
				references.push_back(ref);
			'''
		)

		// Create operations of realized interface in broadcast class
		for (operation : intf.operations) {
			val parameterNames = new BasicEList<String>();
			val parameterTypes = new BasicEList<Type>();
			val parameterNamesWithReturn = new BasicEList<String>();
			val parameterTypesWithReturn = new BasicEList<Type>();
			for (parameter : operation.ownedParameters) {
				if (parameter.direction != ParameterDirectionKind.RETURN_LITERAL) {
					parameterNames.add(parameter.name)
					parameterTypes.add(parameter.type)
				}
				parameterNamesWithReturn.add(parameter.name)
				parameterTypesWithReturn.add(parameter.type)
			}

			// Copy operation of interface in class
			val copiedOperation = EcoreUtil.copy(operation);
			// val copiedOperation = copier.getCopy(operation);
			broadcastClass.ownedOperations.add(copiedOperation);
			var delegationOperation = copiedOperation;

			// Copy stereotype applications
			cppToOO.copyCppOperationAndParameterStereotypes(operation, copiedOperation)

			// Create body
			var delegateOperationCall = '''
				«operation.name»(
					«FOR parameterName : parameterNames SEPARATOR ", "»
						«parameterName»
					«ENDFOR»)
			'''.toString.trim
		
			val hasReturn = parameterNamesWithReturn.size > parameterNames.size
			val delegationOperationBody = '''
				for (unsigned int i = 0; i < references.size()«IF hasReturn» - 1«ENDIF»; i++) {
					references[i]->«delegateOperationCall»;
				}
				«IF hasReturn»
					return references[references.size() - 1]->«delegateOperationCall»;
				«ENDIF»
			'''

			val delegationOperationBehavior = broadcastClass.createOwnedBehavior(opName,
				UMLPackage.eINSTANCE.getOpaqueBehavior()) as OpaqueBehavior
			delegationOperation.getMethods().add(delegationOperationBehavior)

			delegationOperationBehavior.getLanguages().add(progLang)
			delegationOperationBehavior.getBodies().add(delegationOperationBody)
		}
		return broadcastClass
	}
}
