<?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\Oop\MethodImplementation;
	use Phast\UUID;

	class EvaluateBooleanExpressionMethodImplementation extends MethodImplementation
	{
		protected function executeInternal(Oms $oms, OmsContext $context, InstanceReference $method, ?array $parms)
		{
			$value = false;
			$returnsAttribute = $oms->getRelatedInstance($method, KnownRelationshipGuids::Evaluate_Boolean_Expression_Method__returns__Boolean_Attribute);
			$sourceInstanceRef = $oms->getRelatedInstance($method, KnownRelationshipGuids::Evaluate_Boolean_Expression_Method__has_source__Executable_returning_Work_Data);
			$booleanOperator = $oms->getRelatedInstance($method, KnownRelationshipGuids::IDR_Evaluate_Boolean_Expression_Method__uses__Boolean_Operator);
			$targetInstanceRef = $oms->getRelatedInstance($method, KnownRelationshipGuids::Evaluate_Boolean_Expression_Method__has_target__Executable_returning_Work_Data);
			
			$sourceInstance = null;
			if ($oms->is_a($sourceInstanceRef, KnownClassGuids::WorkSet))
			{
				$sourceInstance = $context->getWorkData($sourceInstanceRef);
			}
			else
			{
				$sourceInstanceWD = $oms->execute($context, $sourceInstanceRef);
				$sourceInstance = $sourceInstanceWD;
				if ($oms->is_a($sourceInstanceWD, KnownClassGuids::WorkSet))
				{
					$sourceInstance = $context->getWorkData($sourceInstanceWD);
				}
			}

			if ($sourceInstance === null)
			{
				$oms->MetadataExceptions[] = new OmsMetadataException("Evaluate Boolean Expression `source instance` is null", array
				(
					"Source Instance Method Binding" => $sourceInstanceRef
				));
				echo ("ERR: `source inst` [ from " . $sourceInstanceRef . " ] null");
				return false;
			}

			if ($booleanOperator->GlobalIdentifier == UUID::parse(KnownInstanceGuids::RelationalOperator__Empty))
			{
				echo ("source instance : " . $sourceInstanceRef);
				if ($oms->is_a($sourceInstanceRef, KnownClassGuids::WorkSet))
				{
					$si = $sourceInstance;
					$sourceInstance = $context->getWorkData($sourceInstance);
					echo ("WARN: work set hack used ( " . $si . " := " . $sourceInstance . " )");
				}
				echo (" compare : " . $sourceInstance);
				echo (" is empty ? ");
				if ($sourceInstance == null)
				{
					echo (" ! yes !");
					$value = true;
				}
				else
				{
					echo (" ! no !");
					$value = false;
				}
			}
			else if ($booleanOperator->GlobalIdentifier == UUID::parse(KnownInstanceGuids::RelationalOperator__NotEmpty))
			{
				if ($sourceInstance !== null)
				{
					$value = true;
				}
				else
				{
					$value = false;
				}
			}
			else if ($targetInstanceRef !== null)
			{
				$targetInstanceWD = $oms->execute($context, $targetInstanceRef, false);
				$targetInstance = $targetInstanceWD;
				if ($targetInstanceWD !== null && $oms->is_a($targetInstanceWD, KnownClassGuids::WorkSet))
				{
					$targetInstance = $context->getWorkData($targetInstanceWD);
				}

				$mx = array
				(
					"Method Instance" => $method,
					"Source Instance Ref" => $sourceInstanceRef,
					"Source Instance WD" => $sourceInstanceWD,
					"Source Instance" => $sourceInstance,
					"Target Instance Ref" => $targetInstanceRef,
					"Target Instance WD" => $targetInstanceWD,
					"Target Instance" => $targetInstance,
					"Boolean Operator" => $booleanOperator
				);
				
				// $oms->MetadataExceptions[] = new OmsMetadataException("EBE called", );
				//$this->printWorkData($context->workData);
				//echo (" @@@@ ");
				
				//echo ("source " . $sourceInstanceRef->InstanceKey . "(" . $sourceInstance->InstanceKey . ") ... operator " . $booleanOperator->InstanceKey . " ... target " . $targetInstanceRef->InstanceKey . "(" . $targetInstance->InstanceKey . ")");

				if ($booleanOperator->GlobalIdentifier == UUID::parse(KnownInstanceGuids::RelationalOperator__ExactMatch))
				{
					$value = $oms->CompareInstanceSets_ExactMatch($sourceInstance, $targetInstance);
				}
				else if ($booleanOperator->GlobalIdentifier == UUID::parse(KnownInstanceGuids::LogicalOperator__EqualTo))
				{
					$source = $context->getWorkData($sourceInstance);
					$target = $context->getWorkData($targetInstance);
					// echo ("EBE check: " . $source->Instance . " ?? " . $target);
					$value = $source === $target;
				}
				else
				{
					echo("err: not implement bool operator " . $booleanOperator);
				}
			}
			else
			{
				echo ("source " . $sourceInstanceRef->InstanceKey . "(" . $sourceInstance->InstanceKey . ") ... operator " . $booleanOperator->InstanceKey . " ... target NULL!");
			}
			if ($returnsAttribute !== null)
			{
				echo ("setting attribute " . $returnsAttribute . " = " . ($value ? "true" : "false"));
				$context->setWorkData($returnsAttribute, $value);
			}
			else
			{
				echo ("EBE returned null attribute");
				$oms->MetadataExceptions[] = new OmsMetadataException("EBE : returned null attribute", array
				(
					"Method Instance" => $method
				));
			}
			return $returnsAttribute;
		}
	}

?>