<?php

namespace Modules\Invoices\SupplierInvoices;

class Controller extends \App\Mvc\Controller\Window\PaginatedListing\PaginatedEntityListing
{

	/**
	 * Indicates if the entity execution should use or not a transaction.
	 * @var Boolean
	 */
	protected $useSqlTransaction=true;

	/**
	 * The list of columns which support ordering.
	 * @var array
	 */
	protected $listOrderingColumns = ['addTime', 'invoiceNumber', 'invoiceDate', 'dueDate', 'invoiceSeries'];


	/**
	 * (non-PHPdoc)
	 * @see \App\Mvc\Controller\Window\PaginatedListing\PaginatedListing::initialize()
	 */
	protected function initialize()
	{
		parent::initialize();

		// OPTIONS
		$this->actionsCfg['delete'] = 				['checkOption' => false];
		$this->actionsCfg['block'] = 				['checkOption' => 'Modules/Invoices/SupplierInvoices-block'];
		$this->actionsCfg['unblock'] = 				['checkOption' => 'Modules/Invoices/SupplierInvoices-unblock'];
		$this->actionsCfg['confirm'] = 				['checkOption' => 'Modules/Invoices/SupplierInvoices-statusUpdate'];
		$this->actionsCfg['unconfirm'] = 			['checkOption' => 'Modules/Invoices/SupplierInvoices-statusUpdate'];
		$this->actionsCfg['compensate'] =           ['checkOption' => false, 'checkSection' => true];

	}

	/**
	 * (non-PHPdoc)
	 * @see \App\Mvc\Controller\Window\PaginatedListing\ListingAbstract::index_alterListParams()
	 */
	protected function index_alterListParams($R)
	{
		$filters = [];

		// overwrite the responsible user and date interval
		if ($R['filters']['idReservation']) {
			$filters['user']['id'] = '0|0';
			$month = \App\Utils\Db\TablesUtilsCached::getInstance()->getYmFromId( \App\Utils\Db\TablesUtils::getInstance()->switchIdReservationConversion($R['filters']['idReservation'], 'normal') );

			$filters['invoiceDate'] = [
				'start' 	=> \Engine\DateTime::createFromIsoDate(sprintf('%s-%s-01', substr($month, 0, 4), substr($month, -2)))->sub(new \DateInterval("P6M"))->format('Y-m-d'),
				'end' 		=> \Engine\DateTime::createFromIsoDate(sprintf('%s-%s-01', substr($month, 0, 4), substr($month, -2)))->add(new \DateInterval("P12M"))->format('Y-m-t')
			];
		}

		if ($filters) {
			$this->listingParams->mergeFilters($filters);
			$this->listingParams->save();
		}
	}

	/**
	 * (non-PHPdoc)
	 * @see \App\Mvc\Controller\Window\PaginatedListing\ListingAbstract::actionList_getModelOutput()
	 */
	protected function actionList_getModelOutput($R)
	{
		$filters = $this->getListingParams()->getFilters();

		if (!\Engine\DateTime::createFromIsoDate($filters['invoiceDate']['start'])->isValid() || !\Engine\DateTime::createFromIsoDate($filters['invoiceDate']['end'])->isValid()) {
			throw new \Engine\Mvc\ControllerException($this->lang['index']['messages']['invoiceDate_mandatory']);
		}

		if (\Engine\DateTime::createFromIsoDate($filters['invoiceDate']['start'])->add(\Engine\DateInterval::createFromIntervalSpec("P{$this->cfg['listingParams']['filters']['invoiceDate']['maxDifference']}D")) < \Engine\DateTime::createFromIsoDate($filters['invoiceDate']['end'])) {
			throw new \Engine\Mvc\ControllerException($this->lang['index']['messages']['invoiceDate_invalidInterval']);
		}

		return parent::actionList_getModelOutput($R);
	}

	/**
	 * (non-PHPdoc)
	 * @see \App\Mvc\Controller\Window\PaginatedListing\ListingAbstract::optionDefineParams()
	 */
	protected function optionDefineParams(\App\Mvc\View\Utils\RowOptions\Option\Option $option , $selection)
	{
		switch($option->getId()) {
			case 'insert':
				if (!$option->determineOperationAvailability(\Entity\SupplierInvoice::insert())) {
					$option->setDisabled();
				}
			break;

			case 'delete':
				foreach ($selection as $selectedItem) {
					if (!$option->determineOperationAvailability(\Entity\SupplierInvoice::delete($selectedItem))) {
						break;
					}
				}
			break;

			case 'update':
				foreach($selection as $selectedItem) {
					if (!$option->determineOperationAvailability(\Entity\SupplierInvoice::update($selectedItem))) {
						break;
					}

					// check if it's confirmed (the entity allows this)
					if (\Entity\SupplierInvoice::select($selectedItem)->statusOp == 'confirmed') {
						$option->setDisabled()->addMessage('warning', $this->lang['index']['options']['reasons']['cantEditConfirmed']);
						break;
					}
				}
			break;

			case 'addRemarksBulk': case 'addRemarks':
				foreach($selection as $selectedItem) {
					if (!$option->determineOperationAvailability(\Entity\SupplierInvoice::update($selectedItem))) {
						break;
					}
				}
			break;

			case 'supplierInvoiceCashBulk': case 'assocImportDoc':
				try {
					$distributeImpDocsBulk = new \Modules\Documents\ImportedDocuments\BulkDistributeImportedDocs\SupplierInvoiceModel($selection);
					$distributeImpDocsBulk->isAvailable(false);
				} catch (\App\MessagesException $e) {
					$option->setDisabled();
					$option->setDescription($e->getMessagesCollector()->getMessageBulk());
				}
				break;

			case 'block':
				foreach($selection as $selectedItem) {
					if (!$option->determineOperationAvailability(\Entity\SupplierInvoice::block($selectedItem))) {
						break;
					}
				}
			break;

			case 'unblock':
				foreach($selection as $selectedItem) {
					if (!$option->determineOperationAvailability(\Entity\SupplierInvoice::unblock($selectedItem))) {
						break;
					}
				}
			break;

			case 'payment':
				foreach ($selection as $selectedItem) {
					$suppInv = \Entity\SupplierInvoice::select($selectedItem);
					if ($suppInv->statusOp != 'confirmed') {
						$option->setDisabled();
					}
				}
			break;

			case 'confirm':
				foreach ($selection as $selectedItem) {
					if (!$option->determineOperationAvailability(\Entity\SupplierInvoice::confirm($selectedItem))) {
						break;
					}
				}
			break;

			case 'unconfirm':
				foreach ($selection as $selectedItem) {
					if (!$option->determineOperationAvailability(\Entity\SupplierInvoice::unconfirm($selectedItem))) {
						break;
					}
				}
			break;

			case 'compensate':
			    try {
			        $compensate = new \Modules\Invoices\SupplierInvoices\Compensate\Model($selection);
			        $compensate->isAvailable(false);
			    } catch (\App\MessagesException $e) {
			        $option->setDisabled()->addMessage('warning', $e->getMessagesCollector()->getMessageBulk());
			        break;
			    }
			break;

			case 'view': case 'filterOrders': case 'filterBalances': case 'filterAutoBalances': case 'files':
			case 'balance': case 'task': case 'importStatements':
			break;

			default:
				return false;
		}

		return true;

	}

	/**
	 * (non-PHPdoc)
	 * @see \App\Mvc\Controller\Window\PaginatedListing\PaginatedEntityListing::insert_createEntityObject()
	 */
	protected function insert_createEntityObject($formData)
	{
	}

	/**
	 * (non-PHPdoc)
	 * @see \App\Mvc\Controller\Window\PaginatedListing\PaginatedListing::update_getDefaultFormData()
	 */
	protected function update_getDefaultFormData($idEntity)
	{
		return [];
	}

	/**
	 * (non-PHPdoc)
	 * @see \App\Mvc\Controller\Window\PaginatedListing\PaginatedEntityListing::update_createEntityObject()
	 */
	protected function update_createEntityObject($formData)
	{
	}

	/**
	 * (non-PHPdoc)
	 * @see \App\Mvc\Controller\Window\PaginatedListing\PaginatedEntityListing::delete_createEntityObject()
	 */
	protected function delete_createEntityObject($idRecord)
	{
		return \Entity\SupplierInvoice::delete($idRecord);
	}


	/**
	 * Blocks invoice(s).
	 * @param Array $R
	 */
	protected function actionBlock($R)
	{
		$msgs = \App\MessagesCollector::create();
		$this->setListingSelection($R['listing']['selection']);

		$ids = $this->getListingSelection()->getList();

		foreach ($ids as $id){
			try {
				\DB::startTransaction();

				$invoice = \Entity\SupplierInvoice::block($id);
				$invoice->save();

				// remove this record from the internal list
				$this->getListingSelection()->delete([$id]);

				// commit the current transaction
				\DB::commitTransaction();
				foreach($invoice->getMessages()->getMessages() as $msg) {
					$msgs->addMessage($msg);
				}
			}
			catch(\App\Entity\Exception $ex) {
				\DB::rollbackTransaction();
				$msgs->addMessage( new \App\Message('warning', sprintf("Error encountered on invoice #%s. Error: %s", $id, $ex->getMessageBulk())) );
			}
		}

		return $this->executeListRecords($R, $msgs);
	}

	/**
	 *
	 * @param Array $R
	 */
	protected function actionUnblock($R)
	{
		$msgs = \App\MessagesCollector::create();
		$this->setListingSelection($R['listing']['selection']);

		$ids = $this->getListingSelection()->getList();

		foreach ($ids as $id){
			try {
				\DB::startTransaction();

				$invoice = \Entity\SupplierInvoice::unblock($id);
				$invoice->save();

				// remove this record from the internal list
				$this->getListingSelection()->delete([$id]);

				// commit the current transaction
				\DB::commitTransaction();
				foreach($invoice->getMessages()->getMessages() as $msg) {
					$msgs->addMessage($msg);
				}
			}
			catch(\App\Entity\Exception $ex) {
				\DB::rollbackTransaction();
				$msgs->addMessage(new \App\Message('warning', sprintf($this->lang['unblock']['error'], \Entity\SupplierInvoice::select($id)->getId())));
			}
		}

		return $this->executeListRecords($R, $msgs);
	}

	/**
	 * Confirms one or more invoices.
	 * @param array $R
	 */
	protected function actionConfirm($R)
	{
		return $this->doConfirm($R, true);
	}

	/**
	 * Unconfirms one or more invoices.
	 * @param array $R
	 */
	protected function actionUnconfirm($R)
	{
		return $this->doConfirm($R, false);
	}

	/**
	 *
	 * @param Array $R
	 * @param Boolean $confirmed
	 */
	protected function doConfirm($R, $confirm)
	{
		$msgs = \App\MessagesCollector::create();
		$this->setListingSelection($R['listing']['selection']);

		$ids = $this->getListingSelection()->getList();

		foreach ($ids as $id){
			try {
				\DB::startTransaction();

				if ($confirm) {
					$invoiceEnt = \Entity\SupplierInvoice::confirm($id);
				} else {
					$invoiceEnt = \Entity\SupplierInvoice::unconfirm($id);
				}
				$invoiceEnt->save();

				// remove this record from the internal list
				$this->getListingSelection()->delete([$id]);

				// commit the current transaction
				\DB::commitTransaction();
			}
			catch(\App\Entity\Exception $ex) {
				\DB::rollbackTransaction();
			}

			foreach($invoiceEnt->getMessages()->getMessages() as $msg) {
				$msgs->addMessage($msg);
			}
		}

		return $this->executeListRecords($R, $msgs);

	}

	/**
	 * (non-PHPdoc)
	 * @see \App\Mvc\Controller\Window\PaginatedListing\ListingAbstract::optionGetEntityName()
	 */
	protected function optionGetEntityName($id)
	{
		return \Entity\SupplierInvoice::select($id)->invoiceNumber;
	}

	/**
	 *
	 * @param array $selection
	 * @return null
	 */
	protected function optionsGetSelectionDescription(array $selection)
	{
		$stats = [
			'prices' => [],
		];
		foreach ($selection as $idInvoice) {
			$invoice = \Entity\SupplierInvoice::select($idInvoice);
			$invoiceCurrency = $invoice->currency;

			if (!isset($stats['prices'][$invoiceCurrency])) {
				$stats['prices'][$invoiceCurrency] = [
					'count' => 0,
					'printTotal' => 0,
					'printValue' => 0,
					'printVat' => 0,
				];
			}

			$stats['prices'][$invoiceCurrency]['count']++;

			$stats['prices'][$invoiceCurrency]['totalValue'] += 	$invoice->totalValue;
			$stats['prices'][$invoiceCurrency]['priceValue'] += 	$invoice->priceValue;
			$stats['prices'][$invoiceCurrency]['vatValue'] += 	    $invoice->vatValue;
		}

		// build the HTML
		$html = "";
		$html.= "<table class='inTooltipPrices'><tbody>";
		foreach ($stats['prices'] as $currency => $priceStats) {
			$decimals = \App\Config\CurrencyDecimals::getCurrencyDecimals($currency);

			$html.= sprintf("<tr><td class='inTooltipPrices amount'>%s</td><td class='inTooltipPrices xcurrency'>%s</td></tr>", number_format($priceStats['totalValue'], $decimals), $currency);
		}
		$html.= "</tbody></table>";

		return $html;
	}

}
