<?php
namespace SabaiApps\Framework\Model\EntityCollection;

/**
 * ForeignEntityEntityCollectionDecorator class for decorating entity collections with foreign entities.
 * Adds functionality to fetch and assign a single foreign entity for each entity in the collection.
 */
class ForeignEntityEntityCollectionDecorator extends AbstractEntityCollectionDecorator {

	protected $_foreignKeyVar, $_foreignEntityName, $_foreignEntities, $_foreignEntityObjectVarName;

	/**
	 * Constructor.
	 *
	 * @param string                   $foreignKeyVar Variable name for the foreign key.
	 * @param string                   $foreignEntityName Name of the foreign entity.
	 * @param AbstractEntityCollection $collection Entity collection to decorate.
	 * @param string|null              $foreignEntityObjectVarName Variable name for the foreign entity object (optional).
	 */
	public function __construct( $foreignKeyVar, $foreignEntityName, AbstractEntityCollection $collection, $foreignEntityObjectVarName = null ) {
		parent::__construct( $collection );
		$this->_foreignKeyVar              = $foreignKeyVar;
		$this->_foreignEntityName          = $foreignEntityName;
		$this->_foreignEntityObjectVarName = isset( $foreignEntityObjectVarName ) ? $foreignEntityObjectVarName : $foreignEntityName;
	}

	/**
	 * Rewinds the collection and fetches foreign entities.
	 */
	#[\ReturnTypeWillChange]
	public function rewind() {
		if ( ! isset( $this->_foreignEntities ) ) {
			$this->_foreignEntities = array();
			if ( $this->_collection->count() > 0 ) {
				$foreign_ids = array_filter( $this->_collection->getArray( $this->_foreignKeyVar, $this->_foreignKeyVar ) );
				if ( ! empty( $foreign_ids ) ) {
					$this->_foreignEntities = $this->_model->getRepository( $this->_foreignEntityName )
						->fetchByIds( $foreign_ids )
						->getArray();
				}
			}
		}
		$this->_collection->rewind();
	}

	/**
	 * Gets the current entity and assigns its foreign entity.
	 *
	 * @return mixed Current entity with foreign entity.
	 */
	#[\ReturnTypeWillChange]
	public function current() {
		$current    = $this->_collection->current();
		$foreign_id = $current->{$this->_foreignKeyVar};
		if ( isset( $this->_foreignEntities[ $foreign_id ] ) ) {
			$current->assignObject( $this->_foreignEntityObjectVarName, $this->_foreignEntities[ $foreign_id ] );
		} else {
			$current->assignObject( $this->_foreignEntityObjectVarName );
		}

		return $current;
	}
}
