<?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 SelectFromInstanceSetMethodImplementation extends MethodImplementation
	{
		protected function executeInternal(Oms $oms, OmsContext $context, InstanceReference $method, ?array $parms)
		{
			$forClass = $oms->getRelatedInstance($method, KnownRelationshipGuids::Method__for__Class);
			$returnsWorkSet = $oms->getRelatedInstance($method, KnownRelationshipGuids::Select_from_Instance_Set_Method__returns__Work_Set);
			$loopOnInstanceSet = $oms->getRelatedInstance($method, KnownRelationshipGuids::Select_from_Instance_Set_Method__uses__Executable_returning_Instance_Set);
			$selectionFunction = $oms->getRelatedInstance($method, KnownRelationshipGuids::Select_from_Instance_Set_Method__uses__Selection_Function);
			$setFunction = $oms->getRelatedInstance($method, KnownRelationshipGuids::Select_from_Instance_Set_Method__uses__Set_Function);
			$functionRAMB = $oms->getRelatedInstance($method, KnownRelationshipGuids::Select_from_Instance_Set_Method__uses_function__Executable_returning_Attribute);
			$comparatorWorkData = $oms->getRelatedInstance($method, KnownRelationshipGuids::Select_from_Instance_Set_Method__uses_comparator__Executable_returning_Work_Data);
			$orderRAMB = $oms->getRelatedInstance($method, KnownRelationshipGuids::Select_from_Instance_Set_Method__uses_order__Executable_returning_Attribute);
			$subsetIndexRAMB = $oms->getRelatedInstance($method, KnownRelationshipGuids::Select_from_Instance_Set_Method__uses_subset_index__Executable_returning_Attribute);
			
			// $targetInstance = $context->getWorkData($forClass);
			$mx = array
			(
				"Method Instance" => $method,
				"Returns Work Set" => $returnsWorkSet,
				"Loop on Instance Set" => $loopOnInstanceSet,
				"Selection Function" => $selectionFunction,
				"Set Function" => $setFunction,
				"Function RAMB" => $functionRAMB,
				"Comparator Work Data" => $comparatorWorkData,
				"Order RAMB" => $orderRAMB,
				"Subset Index RAMB" => $subsetIndexRAMB,
				"For Class" => $forClass
			);
			
			$singular = $oms->getAttributeValue($returnsWorkSet, KnownAttributeGuids::Singular);
			if ($singular != 1)
			{
				$singular = $oms->getAttributeValue($method, KnownAttributeGuids::Singular);
			}

			$valuesWD = $oms->execute($context, $loopOnInstanceSet);
			$values = $context->getWorkData($valuesWD);
			$retval = array();
			foreach ($values as $value)
			{
				if ($functionRAMB !== null)
				{
					// execute function to determine if we keep it in the set
					// return true if it should be kept, false if it should be discarded

					$valuePC = $oms->getParentClass($value);
					$context->setWorkData($valuePC, $value);

					$ramb = $oms->execute($context, $functionRAMB);
					$val = $context->getWorkData($ramb);
					if ($val)
					{
						$retval[] = $value;
					}
				}
			}
			if ($singular == 1)
			{
				if (count($retval) > 0)
				{
					$value = $retval[0];
				}
				else
				{
					$value = null;
				}
			}
			else
			{
				//$oms->MetadataExceptions[] = new OmsMetadataException("GRS: returning nonsingular work set", $mx, $context->CallStack, OmsMetadataExceptionSeverity::Information);
				$value = $retval;
			}
			$mx["Got Value"] = $oms->getInstanceKeysString($value);
			$context->setWorkData($returnsWorkSet, $value);
			// $oms->MetadataExceptions[] = new OmsMetadataException("SS called", $mx, $context->CallStack);
			
			//$this->MetadataExceptions[] = new OmsMetadataException("GRS", $mx, null, OmsMetadataExceptionSeverity::Information);
			return $returnsWorkSet;
		}
	}

?>