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

use SabaiApps\Framework\Criteria\InCriteria;

/**
 * AssocEntitiesCountEntityCollectionDecorator class for decorating entity collections with associated entity counts.
 * Adds functionality to calculate and assign the count of associated entities for each entity in the collection.
 */
class AssocEntitiesCountEntityCollectionDecorator extends AbstractEntityCollectionDecorator {

	protected $_linkEntityName, $_linkSelfKey, $_assocEntityName, $_assocEntitiesCount;

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

	/**
	 * Rewinds the collection and calculates associated entity counts.
	 */
	#[\ReturnTypeWillChange]
	public function rewind() {
		$this->_collection->rewind();
		if ( ! isset( $this->_assocEntitiesCount ) ) {
			$this->_assocEntitiesCount = array();
			if ( $this->_collection->count() > 0 ) {
				$criteria = new InCriteria( $this->_linkSelfKey, $this->_collection->getAllIds() );
				$fields   = array( $this->_linkSelfKey, 'COUNT(*) AS cnt' );
				if ( $rs = $this->_model->getGateway( $this->_linkEntityName )->selectByCriteria( $criteria, $fields, 0, 0, null, null, $this->_linkSelfKey ) ) {
					foreach ( $rs as $row ) {
						$this->_assocEntitiesCount[ $row[ $this->_linkSelfKey ] ] = $row['cnt'];
					}
				}
				$this->_collection->rewind();
			}
		}
	}

	/**
	 * Gets the current entity and assigns the associated entity count.
	 *
	 * @return mixed Current entity with associated entity count.
	 */
	#[\ReturnTypeWillChange]
	public function current() {
		$current = $this->_collection->current();
		$count   = isset( $this->_assocEntitiesCount[ $current->id ] ) ? $this->_assocEntitiesCount[ $current->id ] : 0;
		$current->assignObject( $this->_assocEntityName . 'Count', $count );

		return $current;
	}
}
