<?php
namespace SabaiApps\Framework\Model;

/**
 * AbstractTreeEntityRepository class for managing hierarchical entities in a tree structure.
 * Provides methods for fetching and counting parent, child, and descendant entities.
 */
abstract class AbstractTreeEntityRepository extends AbstractEntityRepository {

	/**
	 * Fetches all descendant entities of a given parent entity.
	 *
	 * @param string $id Parent entity ID.
	 * @return AbstractEntityCollection Collection of descendant entities.
	 */
	public function fetchDescendantsByParent( $id ) {
		return $this->_getCollection( $this->_model->getGateway( $this->getName() )->selectDescendants( $id, array() ) );
	}

	/**
	 * Counts all descendant entities of a given parent entity.
	 *
	 * @param string $id Parent entity ID.
	 * @return int Number of descendant entities.
	 */
	public function countDescendantsByParent( $id ) {
		return $this->_model->getGateway( $this->getName() )->countDescendants( $id );
	}

	/**
	 * Fetches all parent entities of a given entity.
	 *
	 * @param string $id Entity ID.
	 * @return AbstractEntityCollection Collection of parent entities.
	 */
	public function fetchParents( $id ) {
		$children = array();
		$rs       = $this->_model->getGateway( $this->getName() )->selectParents( $id, array() );
		foreach ( $rs as $row ) {
			$children[ $row['term_parent'] ] = $row;
		}
		$current = 0;
		$ret     = array();
		while ( isset( $children[ $current ] ) ) {
			$ret[]   = $this->create()->initVars( $children[ $current ] );
			$current = $children[ $current ]['term_id'];
		}
		return $this->createCollection( $ret );
	}

	/**
	 * Counts all parent entities of a given entity.
	 *
	 * @param string $id Entity ID.
	 * @return int Number of parent entities.
	 */
	public function countParents( $id ) {
		return $this->_model->getGateway( $this->getName() )->countParents( $id );
	}

	/**
	 * Counts parent entities for multiple entity IDs.
	 *
	 * @param array $ids Array of entity IDs.
	 * @return array Associative array of entity IDs and their parent counts.
	 */
	public function countParentsByIds( $ids ) {
		$ret = array();
		$rs  = $this->_model->getGateway( $this->getName() )->countParentsByIds( $ids )->getIterator();
		$rs->rewind();
		while ( $rs->valid() ) {
			$row            = $rs->row();
			$ret[ $row[0] ] = $row[1];
			$rs->next();
		}
		return $ret;
	}

	/**
	 * Counts descendant entities for multiple entity IDs.
	 *
	 * @param array $ids Array of entity IDs.
	 * @return array Associative array of entity IDs and their descendant counts.
	 */
	public function countDescendantsByIds( $ids ) {
		$ret = array();
		$rs  = $this->_model->getGateway( $this->getName() )->countDescendantsByIds( $ids )->getIterator();
		$rs->rewind();
		while ( $rs->valid() ) {
			$row            = $rs->row();
			$ret[ $row[0] ] = $row[1];
			$rs->next();
		}
		return $ret;
	}
}
