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

use SabaiApps\Framework\Criteria\InCriteria;

/**
 * AssocEntitiesEntityCollectionDecorator class for decorating entity collections with associated entities.
 * Adds functionality to fetch and assign associated entities for each entity in the collection.
 */
class AssocEntitiesEntityCollectionDecorator extends AbstractEntityCollectionDecorator {

	protected $_linkEntityName, $_linkSelfKey, $_assocEntityTable, $_assocEntityName, $_assocEntities;

	/**
	 * Constructor.
	 *
	 * @param string                   $linkEntityName Name of the linking entity.
	 * @param string                   $linkSelfKey Key used to link entities.
	 * @param string                   $assocEntityTable Table name of the associated entity.
	 * @param string                   $assocEntityName Name of the associated entity.
	 * @param AbstractEntityCollection $collection Entity collection to decorate.
	 */
	public function __construct( $linkEntityName, $linkSelfKey, $assocEntityTable, $assocEntityName, AbstractEntityCollection $collection ) {
		parent::__construct( $collection );
		$this->_linkEntityName   = $linkEntityName;
		$this->_linkSelfKey      = $linkSelfKey;
		$this->_assocEntityTable = $assocEntityTable;
		$this->_assocEntityName  = $assocEntityName;
	}

	/**
	 * Rewinds the collection and fetches associated entities.
	 */
	#[\ReturnTypeWillChange]
	public function rewind() {
		$this->_collection->rewind();
		if ( ! isset( $this->_assocEntities ) ) {
			$this->_assocEntities = array();
			if ( $this->_collection->count() > 0 ) {
				$criteria = new InCriteria( $this->_linkSelfKey, $this->_collection->getAllIds() );
				$fields   = array( $this->_linkSelfKey, $this->_assocEntityTable . '.*' );
				if ( $rs = $this->_model->getGateway( $this->_linkEntityName )->selectByCriteria( $criteria, $fields ) ) {
					foreach ( $rs as $row ) {
						$entity = $this->_model->create( $this->_assocEntityName );
						$entity->initVars( $row );
						$this->_assocEntities[ $row[ $this->_linkSelfKey ] ][] = $entity;
					}
				}
				$this->_collection->rewind();
			}
		}
	}

	/**
	 * Gets the current entity and assigns the associated entities.
	 *
	 * @return mixed Current entity with associated entities.
	 */
	#[\ReturnTypeWillChange]
	public function current() {
		$current  = $this->_collection->current();
		$id       = $current->id;
		$entities = ! empty( $this->_assocEntities[ $id ] ) ? $this->_assocEntities[ $id ] : array();
		$current->assignObject( $this->_assocEntityName, $this->_model->createCollection( $this->_assocEntityName, $entities ) );

		return $current;
	}
}
