<?php
	namespace Mocha\Oop\MethodImplementations;

	use Mocha\Core\InstanceReference;
	use Mocha\Core\KnownAttributeGuids;
	use Mocha\Core\KnownClassGuids;
	use Mocha\Core\KnownInstanceGuids;
	use Mocha\Core\KnownRelationshipGuids;
	use Mocha\Core\OmsContext;
	use Mocha\Oms\Oms;
	use Mocha\Oms\OmsMetadataException;
	use Mocha\Oms\OmsMetadataExceptionSeverity;
	use Mocha\Oop\MethodImplementation;

	use Phast\UUID;

	class GetReferencedAttributeMethodImplementation extends MethodImplementation
	{
		protected function executeInternal(Oms $oms, OmsContext $context, InstanceReference $method, ?array $parms)
		{
			$returnsAttribute = $oms->getRelatedInstance($method, KnownRelationshipGuids::Get_Referenced_Attribute_Method__returns__Attribute);
			$forClass = $oms->getRelatedInstance($method, KnownRelationshipGuids::Method__for__Class);
			$loopOnInstanceSet = $oms->getRelatedInstance($method, KnownRelationshipGuids::Get_Referenced_Attribute_Method__uses_reference__Executable_returning_Instance_Set);
			$answer = $oms->getRelatedInstance($method, KnownRelationshipGuids::Get_Referenced_Attribute_Method__uses_answer__Executable_returning_Attribute);
			$targetInstance = $context->getWorkData($forClass);
			
			if ($oms->is_a($loopOnInstanceSet, KnownClassGuids::MethodBinding))
			{
				$loopOnInstanceSetTarget = $oms->execute($context, $loopOnInstanceSet);
				if ($loopOnInstanceSetTarget === null)
				{
				}
				$targetInstance = $context->getWorkData($loopOnInstanceSetTarget);
			}

			$refISRel = $oms->execute($context, $loopOnInstanceSet);
			$mx = array
			(
				"Method Instance" => $method,
				"Returns Attribute" => $returnsAttribute,
				"Loop on Instance Set" => $loopOnInstanceSet,
				"Get Attribute" => $answer,
				"For Class" => $forClass,
				"Target Instance" => $targetInstance,
				"Referenced Instance Relationship" => $refISRel,
			);
			if ($refISRel !== null)
			{
				$refIS = $context->getWorkData($refISRel);
				if ($refIS !== null)
				{
					$pc = $oms->getParentClass($refIS);
					if ($pc !== null)
					{
						$context->setWorkData($pc, $refIS);
					}
					else
					{
						$oms->MetadataExceptions[] = new OmsMetadataException("missing parent class for instance", array
						(
							"Instance" => $refIS
						));
					}
					
					$answerVal = $oms->execute($context, $answer);
					$mx["Answer Work Data"] = $answerVal;
					
					$value = $context->getWorkData($answerVal); // $this->getAttributeValue($refIS, $answer);
					$mx["Answer Value"] = $value;
					$context->setWorkData($returnsAttribute, $value);

					//$oms->MetadataExceptions[] = new OmsMetadataException("GRA call", $mx, $context->CallStack, OmsMetadataExceptionSeverity::Information);
				}
				else
				{
					$oms->MetadataExceptions[] = new OmsMetadataException("GRA : Loop on Instance Set returned a value, but that value returned null", $mx);
				}
			}
			else
			{
				$oms->MetadataExceptions[] = new OmsMetadataException("Loop on Instance Set returned null for `Get Referenced Attribute Method.uses reference Executable returning Attribute`", array
				(
					"Method Instance" => $method,
					"Loop on Instance Set" => $loopOnInstanceSet
				), $context->CallStack);
			}
			return $returnsAttribute;
		}
	}

?>