<?php
namespace App\Dashboard\Widget;

abstract class ClientLastInvoices extends \Engine\Dashboard\Widgets\WidgetAbstract
{
	/**
	 * The default cache lifetime.
	 * @var Int
	 */
	protected $cacheLifetime=1800;

	/**
	 * The default options associated when the widget is added.
	 * @var array
	 */
	protected function getDefaultOptions()
	{
		$return = [
			'invStartDate' => 		'1month',
			'temporaryInvoices' =>  'notTemporary',
			'voided' => 			'0',
			'issued' => 			'2',
			'cashed' => 			'',
			'userType' => 			'responsible',
			'columnsList' => 		['number', 'date', 'due', 'duePassedDays', 'value', 'responsible', 'issued', 'voided', 'temporary', 'viewOption'],
			'selectLimit' => 		5,
		];
		return $return;
	}

	/**
	 * (non-PHPdoc)
	 * @see \Engine\Dashboard\Widgets\WidgetAbstract::getWidgetCacheLifeDurations()
	 */
	protected function getWidgetCacheLifeDurations()
	{
		#return array(14400, 21600, 28800, 36000, 43200, 86400);
		return parent::getWidgetCacheLifeDurations();
	}

	/**
	 * Get the parameters that will be sent down to the TPL file
	 * @return Array
	 */
	public function getTemplateParams()
	{

		$templateParams = parent::getTemplateParams();

		// populate invoices list url
		$params = [];
		$params['filters'] = $this->getInvoicesListFilters($templateParams['options']);
		$params['listing']['paramsSlot'] = "1";
		$params['listing']['reset'] = "1";

		$templateParams['invoicesListUrl'] = \Engine\Mvc\Dispatcher::getInstance()->getAppUrl('Modules/Invoices/InvoicesList', 'index', $params);

		return $templateParams;
	}

	/**
	 * Returs the invoices list filter
	 * @param array $options
	 * @return Array
	 */
	protected function getInvoicesListFilters(Array $options)
	{
		$invoicesListFilters = [];

		// apply invoice date filter
		if (!$options['invStartDate']) {
			$invoiceDate = TODAY_ISO;
		}
		else {
			$invoiceDate = \Engine\DateTime::create()->modify("-{$options['invStartDate']}")->formatDateIso();
		}

		$invoicesListFilters['invoiceDate']['start'] = $invoiceDate;
		$invoicesListFilters['invoiceDate']['end'] = \Engine\DateTime::create()->formatDateIso();

		// filter by temporary invoice
		$invoicesListFilters['temporaryInvoices'] = $options['temporaryInvoices'];

		// apply voided filter
		if ($options['voided'] == 1) {
			$invoicesListFilters['voidedInvoices'] = 'voided';
		}
		elseif ($options['voided'] == 0) {
			$invoicesListFilters['voidedInvoices'] = 'notVoided';
		}
		else {
			$invoicesListFilters['voidedInvoices'] = 'all';
		}

		// apply issued filter
		if ($options['issued'] == 1) {
			$invoicesListFilters['issuedInvoices'] = 'issued';
		}
		elseif ($options['issued'] == 0) {
			$invoicesListFilters['issuedInvoices'] = 'notIssued';
		}
		else {
			$invoicesListFilters['issuedInvoices'] = 'all';
		}

		// apply cashed filter
		if ($options['cashed'] == 'n' or $options['cashed'] == 'p' or $options['cashed'] == 't' or $options['cashed'] == 'o') {
			$invoicesListFilters['cashedStatus'] = $options['cashed'];
		}
		elseif ($options['cashed'] == 'np') {
			$invoicesListFilters['cashedStatus'] = $options['cashed'];
		}
		elseif ($options['cashed'] == 'to') {
			$invoicesListFilters['cashedStatus'] = $options['cashed'];
		}
		else {
			$invoicesListFilters['cashedStatus'] = '';
		}

		// user type = all
		if ($options['userType'] == 'all') {
			// nothing to do
			$invoicesListFilters['resIdOfficeUser']['id'] = "0|0";
		}
		// user type = responsible
		elseif ($options['userType'] == 'responsible') {
			$invoicesListFilters['resIdOfficeUser']['id'] = "|".CURRENT_ID_USER;
		}

		if ($this->getOption_rec('idCorporate')) {
			$invoicesListFilters['clientType'] = 'corp';
			$invoicesListFilters['idCorporateOffice']['id'] = $this->getOption_rec('idCorporate')."|0";
		}
		elseif ($this->getOption_rec('idCustomer')) {
			$invoicesListFilters['clientType'] = 'cust';
			$invoicesListFilters['idCustomer']['id'] = $this->getOption_rec('idCustomer');
		}

		return $invoicesListFilters;
	}

	/**
	 * Returns the columns codes
	 * @return multitype:string
	 */
	protected function getColsCodes()
	{
		return ['number', 'date', 'due', 'duePassedDays', 'value', 'responsible', 'issued', 'voided', 'temporary', 'viewOption'];
	}


	/**
	 * Generate the options form
	 */
	protected function populateLocalOptionsForm(\Engine\Form\Container\GeneralAbstract $form)
	{
		$calledClass = get_called_class();
		$className = stripClassNamespace($calledClass);

		// load lang
		$loaderLang = \App\Loader_Lang::getInstance();
		$loaderLang->loadAppFile("_customLoad/dashboard/widgets/_general.lang.php");
		$loaderLang->loadAppFile("_customLoad/dashboard/widgets/{$className}.lang.php");
		$loaderLang->loadAppFile("_customLoad/dashboard/widgets/ClientLastInvoices.lang.php");
		$_LANG = $loaderLang->getAll();

		$fieldset = \Engine\Form\Container\Fieldset::create($_LANG['dashboard']['widgets']['_GENERAL_']['formFields']['specificFieldsLegend']);

		/*-------------------------------------------*/

		// invoice period
		$field = new \Engine\Form\Input\Select($_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['invStartDate'], 'invStartDate', $this->getOption('invStartDate'));
		$periods = ['', '1day', '2days', '3days', '4days', '5days', '1week', '2weeks', '3weeks', '1month', '2months', '3months', '6months', '9months', '1year',];
		$vals = [];
		foreach ($periods as $per) {
			$vals[$per] = $_LANG['dashboard']['widgets']['_GENERAL_']['timePeriods'][$per];
		}
		$field->setPossibleValues($vals);
		$fieldset->addElement($field);

		// invoice temporary
		$field = new \Engine\Form\Input\Select($_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['temporaryInvoices'], 'temporaryInvoices', $this->getOption('temporaryInvoices'));
		$field->setPossibleValues( [
			'' =>						$_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['allTemporaryInvoices'],
			'notTemporary' => 			$_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['notTemporaryInvoices'],
			'temporaryNotCumulated' => 	$_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['temporaryNotCumulatedInvoices'],
			'temporaryCumulated' => 	$_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['temporaryCumulatedInvoices'],
			'cumulative' => 			$_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['cumulatedInvoices'],
		]);
		$fieldset->addElement($field);

		// invoice void status
		$field = new \Engine\Form\Input\Select($_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['voidStatus'], 'voided', $this->getOption('voided'));
		$vals = [
			2 => $_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['voidStatus_2'],
			0 => $_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['voidStatus_0'],
			1 => $_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['voidStatus_1']
		];
		$field->setPossibleValues($vals);
		$fieldset->addElement($field);

		// invoice issued status
		$field = new \Engine\Form\Input\Select($_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['issueStatus'], 'issued', $this->getOption('issued'));
		$vals = [
			2 => $_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['issueStatus_2'],
			1 => $_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['issueStatus_1'],
			0 => $_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['issueStatus_0']
		];
		$field->setPossibleValues($vals);
		$fieldset->addElement($field);

		// invoice cashed status
		$field = new \Engine\Form\Input\Select($_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['cashedStatus'], 'cashed', $this->getOption('cashed'));
		$vals = [
			'' => 	$_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['cashedStatus_all'],
			'n' => 	$_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['cashedStatus_n'],
			'p' => 	$_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['cashedStatus_p'],
			'np' => $_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['cashedStatus_np'],
			't' => 	$_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['cashedStatus_t'],
			'o' => 	$_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['cashedStatus_o'],
			'to' => $_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['cashedStatus_to']
		];
		$field->setPossibleValues($vals);
		$fieldset->addElement($field);

		// invoice user type
		$field= new \Engine\Form\Input\Select($_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['userType'], 'userType', $this->getOption('userType'));
		$vals = [
			'all' => 			$_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['userType_all'],
			'responsible' => 	$_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['userType_resp'],
			'kam' => 			$_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['userType_kam'],
			'both' => 			$_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['userType_both']];
		$field->setPossibleValues($vals);
		$field->setTooltip($_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['userTypeTooltip']);
		$fieldset->addElement($field);

		// listing columns
		$field = new \Engine\Form\Input\Checkboxes($_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['chooseColumns'], 'columnsList', $this->getOption('columnsList'));
		$cols = $this->getColsCodes();
		$vals = [];
		foreach($cols as $col) {
			$vals[$col] = $_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['columnsList'][$col];
		}
		$field->setPossibleValues($vals);
		$fieldset->addElement($field);

		// listing limit
		$field = new \Engine\Form\Input\Select($_LANG['dashboard']['widgetsList']['App\Dashboard\Widget\ClientLastInvoices']['options']['selectLimit'], 'selectLimit', $this->getOption('selectLimit'));
		$vals = [
			'5' => 	$_LANG['dashboard']['widgets']['_GENERAL_']['selectLimits']['5'],
			'10'=>	$_LANG['dashboard']['widgets']['_GENERAL_']['selectLimits']['10']
		];
		$field->setPossibleValues($vals);
		$fieldset->addElement($field);

		$form->addContainer($fieldset);
		return $form;
	}


	/**
	 * Extract data from the form return($R) and sets internal configs($this->options) accordingly
	 */
	protected function extractFormOptions($formData)
	{
		$options = [];

		$options['invStartDate'] = 		$formData['invStartDate'];
		$options['temporaryInvoices'] = $formData['temporaryInvoices'];
		$options['voided'] = 			$formData['voided'];
		$options['issued'] = 			$formData['issued'];
		$options['cashed'] = 			$formData['cashed'];
		$options['userType'] = 			$formData['userType'];

		if ($formData['columnsList'] && is_array($formData['columnsList'])) {
			$options['columnsList'] = array_keys($formData['columnsList']);
		}
		else {
			$options['columnsList'] = [];
		}

		$options['selectLimit'] = 	$formData['selectLimit'];

		$this->setOptions($options);
	}


	/**
	 * Sets the collected processed data.
	 * @return Array
	 */
	public function getData()
	{
		// if no columns selected - do not go on
		if (!$this->getOption('columnsList') or !is_array($this->getOption('columnsList'))) {
			return false;
		}

		// get columns in an associative array
		$colsAssoc = array_combine($this->getOption('columnsList'), array_fill(0, count($this->getOption('columnsList')), true));

		$output = [];

		$calledClass = get_called_class();
		$className = stripClassNamespace($calledClass);

		// load lang
		$loaderLang = \App\Loader_Lang::getInstance();
		$loaderLang->loadAppFile("_customLoad/dashboard/widgets/_general.lang.php");
		$loaderLang->loadAppFile("_customLoad/dashboard/widgets/{$className}.lang.php");
		$loaderLang->loadAppFile("_customLoad/dashboard/widgets/ClientLastInvoices.lang.php");
		$_LANG = $loaderLang->getAll();

		// validate customer
		if ($this->getOption_rec('idCustomer')) {
			$customerEntity = \Entity\Customer::select($this->getOption_rec('idCustomer'));

			if (!$customerEntity->recordExists()) {
				$output['errorMessage'] = $_LANG['dashboard']['widgetsList'][$calledClass]['messages']['invalidIdCustomer'];
			}
			elseif ($customerEntity->deleted) {
				$output['errorMessage'] = $_LANG['dashboard']['widgetsList'][$calledClass]['messages']['customerDeleted'];
			}
		}

		// validate corporate
		if ($this->getOption_rec('idCorporate')) {
			$corporateEntity = \Entity\Corporate::select($this->getOption_rec('idCorporate'));

			if (!$corporateEntity->recordExists()) {
				$output['errorMessage'] = $_LANG['dashboard']['widgetsList'][$calledClass]['messages']['invalidIdCorporate'];
			}
			elseif ($corporateEntity->deleted) {
				$output['errorMessage'] = $_LANG['dashboard']['widgetsList'][$calledClass]['messages']['customerDeleted'];
			}
		}

		if (!$output['errorMessage']) {
			// GET THE INVOICES LIST //////////////////////////////////////////////////////////////
			$invoicesListObj = new \App\EntityList\Invoices();

			// APPLY CERTAIN FILTER ON THE INVOICES ///////////////////////////////////////////////

			// apply invoice date filter
			if (!$this->getOption('invStartDate')) {
				$invoiceDate = TODAY_ISO;
			}
			else {
				$invoiceDate = \Engine\DateTime::create()->modify("-{$this->getOption('invStartDate')}")->formatDateIso();
			}

			$invoicesListObj->setFilter('inv.invoiceDate', '>=', $invoiceDate);

			// filter by client
			$this->filterByClient($invoicesListObj);

			// filter by temporary invoice
			switch ($this->getOption('temporaryInvoices')) {
				case 'notTemporary':
					$invoicesListObj->setFilter('temporary', '=', '0');
				break;

				case 'temporaryNotCumulated':
					$invoicesListObj->setFilter('temporary', '=', '1');
					$invoicesListObj->setFilter('cumulatedOnInvoiceId', '=', '0');
				break;

				case 'temporaryCumulated':
					$invoicesListObj->setFilter('temporary', '=', '1');
					$invoicesListObj->setFilter('cumulatedOnInvoiceId', '>', '0');
				break;

				case 'cumulative':
					$invoicesListObj->setFilter('cumulativeInvoice', '=', '1');
				break;
			}

			// apply voided filter
			if ($this->getOption('voided') == 1) {
				$invoicesListObj->setFilter('inv.voidTime', '>', 0);
			}
			elseif ($this->getOption('voided') == 0) {
				$invoicesListObj->setFilter('inv.voidTime', '=', 0);
			}

			// apply issued filter
			if ($this->getOption('issued') == 1) {
				$invoicesListObj->setFilter('inv.issueTime', '>', 0);
			}
			elseif ($this->getOption('issued') == 0) {
				$invoicesListObj->setFilter('inv.issueTime', '=', 0);
			}

			// apply cashed filter
			if ($this->getOption('cashed') == 'n' or $this->getOption('cashed') == 'p' or $this->getOption('cashed') == 't' or $this->getOption('cashed') == 'o') {
				$invoicesListObj->setFilter('inv.cashedStatus', '=', $this->getOption('cashed'));
			}
			elseif ($this->getOption('cashed') == 'np') {
				$invoicesListObj->setFilter('inv.cashedStatus', 'IN', ['n', 'p']);
			}
			elseif ($this->getOption('cashed') == 'to') {
				$invoicesListObj->setFilter('inv.cashedStatus', 'IN', ['t', 'o']);
			}

			// user type = all
			if ($this->getOption('userType') == 'all') {
				// nothing to do
			}
			// user type = responsible
			elseif ($this->getOption('userType') == 'responsible') {
				$invoicesListObj->setFilter('inv.idUser', '=', CURRENT_ID_USER);
			}
			// user type = kam
			elseif ($this->getOption('userType') == 'kam') {
				$corpsList = \Entity\User::selectCurrent()->kamCorporatesList;
				if ($corpsList) {
					$invoicesListObj->setFilter('inv.idCorporate', 'IN', $corpsList);
				}
				else {
					$invoicesListObj->setFilter('inv.idCorporate', '=', 0);
				}
			}
			// user type = both
			elseif ($this->getOption('userType') == 'both') {
				$corpsList = \Entity\User::selectCurrent()->kamCorporatesList;
				$bv = [];
				$filter = "inv.idUser=?";
				$bv[] = CURRENT_ID_USER;
				if ($corpsList) {
					$filter.=" OR inv.idCorporate IN (".implode(',', array_fill(0, count($corpsList), '?')).")";
					$bv = array_merge($bv, $corpsList);
				}

				$invoicesListObj->setCustomFilter($filter, $bv);
			}

			// apply user restrictions
			$invoicesListObj->applyUserRestriction(true);


			// ASSOCIATE COLUMNS FOR THIS LISTING -----------------------------------------------------
			$invoicesListObj->setColumn('inv.invoiceNumber');
			$invoicesListObj->setColumn('inv.idInvoiceSeries');
			$invoicesListObj->setColumn('inv.invoiceDate');
			$invoicesListObj->setColumn('inv.dueDate');
			$invoicesListObj->setColumn('inv.idCustomer');
			$invoicesListObj->setColumn('inv.idCorporate');
			$invoicesListObj->setColumn('inv.printTotal');
			$invoicesListObj->setColumn('inv.currency');
			$invoicesListObj->setColumn('inv.cashedTotal');
			$invoicesListObj->setColumn('inv.cashedStatus');
			$invoicesListObj->setColumn('inv.idUser');
			$invoicesListObj->setColumn('inv.idOffice');
			$invoicesListObj->setColumn('inv.issueTime');
			$invoicesListObj->setColumn('inv.idIssueUser');
			$invoicesListObj->setColumn('inv.temporary');
			$invoicesListObj->setColumn('inv.cumulatedOnInvoiceId');
			$invoicesListObj->setColumn('inv.cumulativeInvoice');
			$invoicesListObj->setColumn('inv.voidTime');
			$invoicesListObj->setColumn('inv.duplicatedOnInvoiceId');
			$invoicesListObj->setColumn('inv.idVoidUser');
			$invoicesListObj->setColumn('inv.addTime'); // we can order by this column

			// OTHER CLAUSES --------------------------------------------------------------------------
			$invoicesListObj->setOrderBy('addTime', 'DESC');
			$invoicesListObj->setLimit($this->getOption('selectLimit'));

			// apply user restriction
			$invoicesListObj->applyUserRestriction(true);
			$invoicesList = $invoicesListObj->exportRecords();

			// populate due passed days
			foreach ($invoicesList as $invoiceIndex => $invoiceDetails) {
				$invoiceDetails['printTotal'] = (float)$invoiceDetails['printTotal'];
				if ($invoiceDetails['dueDate']) {

					// calculate due passed days for not payed or partially payed invoices
					if (in_array($invoiceDetails['cashedStatus'], ['n', 'p'])) {
						$invoiceDetails['duePassedDays'] = (int)\Engine\DateTime::createFromIsoDate($invoiceDetails['dueDate'])->diff(\Engine\DateTime::createFromIsoDate(TODAY_ISO), false)->format("%r%a");
					}
					else {
						$invoiceEntity = \Entity\Invoice::select($invoiceDetails['id']);
						$invoiceDetails['duePassedDays'] = (int)\Engine\DateTime::createFromIsoDate($invoiceDetails['dueDate'])->diff(\Engine\DateTime::createFromIsoDate($invoiceEntity->lastCashingDocumentDate), false)->format("%r%a");
					}
				}

				$invoicesList[$invoiceIndex] = $invoiceDetails;
			}


			// ASSOCIATE THE DATA FOR THE LISTING /////////////////////////////////////////////////////
			$output['invoicesList'] = $invoicesList;
		}

		// ASSOCIATE OTHER INFO ///////////////////////////////////////////////////////////////////
		$output['columnsListAssoc'] = $colsAssoc;

		return $output;
	}

	/**
	 * (non-PHPdoc)
	 * @see \Engine\Dashboard\Widgets\WidgetAbstract::loadLangs()
	 */
	public function loadLangs()
	{
		$thisClass = stripClassNamespace(get_called_class());

		// load langs
		$loaderLang = \App\Loader_Lang::getInstance();
		$loaderLang->loadAppFile("_customLoad/dashboard/widgets/_general.lang.php");
		$loaderLang->loadAppFile("_customLoad/dashboard/widgets/".$thisClass.".lang.php");
		$loaderLang->loadAppFile("_customLoad/dashboard/widgets/ClientLastInvoices.lang.php");
	}

	/**
	 * Filter invoices by client
	 * @param \App\EntityList\Invoices $invoicesListObj
	 * @throws \Engine\Dashboard\Exception
	 */
	protected function filterByClient(\App\EntityList\Invoices $invoicesListObj)
	{
		if ($this->getOption_rec('idCorporate')) {
			$invoicesListObj->setFilter('inv.idCorporate', '=', $this->getOption_rec('idCorporate'));
		}
		elseif ($this->getOption_rec('idCustomer')) {
			$invoicesListObj->setFilter('inv.idCustomer', '=', $this->getOption_rec('idCustomer'));
		}
		else {
			throw new \Engine\Dashboard\Exception("No option specified");
		}
	}
}
