<?php
namespace ModulesAbstract\PluginReports\Report\Model\Gatherer;

/**
 * Invoice reservation gatherer
 * The output will be a list of service id's
 * This class is equivalent with GENRGatherer_ReservationServices
 * @author Oana Stan
 */
class OrderServices extends GathererAbstract
{
	/**
	 * Recordset resulted after $db->Execute
	 */
	protected $orderServicesIterator = NULL;

	/**
	 * Stores last reported row
	 * @var String
	 */
	protected $lastReportedKey = NULL;

	/**
	 * (non-PHPdoc)
	 * @see \ModulesAbstract\PluginReports\Report\Model\Gatherer\GathererAbstract::getRequiredFilters()
	 */
	public function getRequiredFilters()
	{
		return [
			'ticketDate',
			'corporatesAndSegmentsAndGroups',
		];
	}

	/**
	 * (non-PHPdoc)
	 * @see \ModulesAbstract\PluginReports\Report\Model\Gatherer\GathererAbstract::objectInitialize()
	 */
	protected function objectInitialize()
	{
		$listObj = new \App\EntityList\OrderServices();

		// get columns
		$listObj->setColumns([
			'serv.id' => 					'idOrderService', // 'idOrderService' is equivalent with idReservationService
			'serv.passengersTicketsDate' => 'ticketDate',
		]);

		//// APPLY FILTERS //////////////////////////////////
		// filter by passenger tickets date
		$listObj->setFilter('serv.passengersTicketsDate', 'BETWEEN', [
			$this->filters['ticketDate']['start'],
			$this->filters['ticketDate']['end'],
		]);

		// filter non cancelled services
		$listObj->setFilter('serv.cancelReason', '=', '');

		// filter services with statusOp 'OK' and statusFin 'TI'
		$listObj->setFilter('serv.statusOp', '=', 'OK');
		$listObj->setFilter('serv.statusFin', '=', 'TI');

		// filter by idUser or idOffice
		if ($this->filters['userAndOffice']['type'] == 'user') {
			if ($this->filters['userAndOffice']['entityId']) {
				$listObj->setFilter('serv.idUser', '=', $this->filters['userAndOffice']['entityId']);
			}
		}
		elseif ($this->filters['userAndOffice']['type'] == 'office') {
			if ($this->filters['userAndOffice']['entityId']) {
				$listObj->setFilter('serv.idOffice', '=', $this->filters['userAndOffice']['entityId']);
			}
		}

		// filter by corporate or segment or groups
		// when filtering by corporate/segment/groups, if the specified segment doesn't contain any corporates, directly return a fake empty resultset
		if (in_array($this->filters['corporatesAndSegmentsAndGroups']['type'], ['segment', 'groups']) && !$this->filters['corporatesAndSegmentsAndGroups']['corporateIds']) {
			$this->orderServicesIterator = new \ADORecordSet_empty();
			return;
		}
		if (in_array($this->filters['corporatesAndSegmentsAndGroups']['type'], ['all', 'corporate', 'segment', 'groups'])) {
			if ($this->filters['corporatesAndSegmentsAndGroups']['corporateIds']) {
				$listObj->setFilter('res.idCorporateOwner', 'IN', $this->filters['corporatesAndSegmentsAndGroups']['corporateIds']);
			}
			else {
				$listObj->setFilter('res.idCorporateOwner', '!=', 0);
			}
		}
		else {
			throw new \Exception(sprintf("%s type is invalid", __METHOD__));
		}

		// order services
		$listObj->setOrderBy('ticketDate', 'ASC');
		$listObj->setOrderBy('idOrderService', 'ASC');
		$listObj->applyUserRestriction(false);

		$this->orderServicesIterator = $listObj->getExecution();
	}

	/**
	 * (non-PHPdoc)
	 * @see \ModulesAbstract\PluginReports\Report\Model\Gatherer\GathererAbstract::objectDestroy()
	 */
	protected function objectDestroy()
	{
		if ($this->orderServicesIterator) {
			$this->orderServicesIterator->Close();
			$this->orderServicesIterator = NULL;
		}
	}

	/**
	 * Generate a unique key, used for grouping rows
	 * @param array $result
	 * @return string
	 */
	protected function generateKey(Array $result)
	{
		return sprintf("%s/%s", $result['idOrderService'], $result['special']);
	}

	/**
	 * (non-PHPdoc)
	 * @see \ModulesAbstract\PluginReports\Report\Model\Gatherer\GathererAbstract::objectNext()
	 */
	protected function objectNext()
	{
		if ($this->orderServicesIterator && !$this->orderServicesIterator->EOF) {
			$result = $this->orderServicesIterator->FetchRow();

			$key = $this->generateKey($result);
			if ($key !== $this->lastReportedKey) {
				$this->lastReportedKey = $key;
				return $result;
			}
			else {
				return "intern:skip"; // skip row
			}
		}
		return NULL;
	}
}