<?php

namespace App\GenDocument\SpecialObject;


class InvoiceStandardTable extends TableAbstract
{

	/**
	 * The list of invoice rows which will be scanned when generating the special object's table.
	 * @var array
	 */
	protected $invoiceRows;

	/**
	 * Stores some extra info about each row.
	 * @var array
	 */
	protected $invoiceRowsExtraInfo;

	/**
	 * Stores the invoice rows totals.
	 * @var array
	 */
	protected $invoiceTotals;

	/**
	 * The columns that
	 * @var array
	 */
	protected $totalCols = ['value', 'valueDefCurr', 'valueWorkCurr', 'vat', 'total', 'totalDefCurr', 'totalWorkCurr', 'valueDefCurrRowCurrDet', 'vatDefCurrRowCurrDet', 'totalDefCurrRowCurrDet'];

	/**
	 * Populates the table content.
	 */
	protected function table_populateRows()
	{

		$this->invoiceStandardTable_setInvoiceRows();

		$this->invoiceStandardTable_rowsExtraProcessing();

		$this->invoiceStandardTable_populateTableRows();

	}

	/**
	 * Populates invoice rows attribute ($this->invoiceRows).
	 */
	protected function invoiceStandardTable_setInvoiceRows()
	{

		$invoiceRowsList = \Entity\Invoice::select($this->idPivot)->visibleRowsList;

		$invoiceRowsList = $this->filterInvoiceRowsList($invoiceRowsList);

		$this->invoiceRows = $invoiceRowsList;

	}

	/**
	 * Filter the invoie rows list
	 * @param array $invoiceRowsList
	 * @return array
	 */
	protected function filterInvoiceRowsList(Array $invoiceRowsList)
	{
		// trim() each specified service code
		$allowedServices = array_filter(array_map(function($code) {
			return trim($code);
		}, explode(",", (String)$this->settings['filterServices'])));

		if ($allowedServices) {
			foreach($invoiceRowsList as $id=>$row) {
				if (!in_array($row['serviceCode'], $allowedServices)) {
					unset($invoiceRowsList[$id]);
				}
			}
		}

		return $invoiceRowsList;
	}

	/**
	 * Populates the attributes: $this->invoiceRowsExtraInfo and $this->invoiceTotals.
	 */
	protected function invoiceStandardTable_rowsExtraProcessing()
	{

		global $CFG;

		// the itinerary format
		$itineraryFormat = [
				'departure' => ['place'=>'stationCodeStandard', 'dateAndTime'=>''],
				'arrival' => ['place'=>'stationCodeStandard', 'dateAndTime'=>'date',],
				'segmentSeparator' => ' ; ', 'segmentGlue' => '-',
		];

		// reset the extra info rows list
		$this->invoiceRowsExtraInfo = [];

		// simplified vars
		$invCurrency=\Entity\Invoice::select($this->idPivot)->currency;
		$invDate=\Entity\Invoice::select($this->idPivot)->invoiceDate;

		// currency types
		$currTypes=\App\Config\CurrencyTypes::getInstance()->getSimple();

		$serviceIndexes = [];
		$currServIdx = 1;

		// LOOP THROUGH EACH ROW AND ADD EXTRA INFO ///////////////////////////////////////////////
		foreach($this->invoiceRows as $id=>$row) {

			// skip empty rows (subtotals)
			if (!$row) continue;

			// determine the service index
			if ($serviceIndexes[$row['idReservationService']] ) {
				$serviceIndexes[$row['idReservationService']]['component']++;
			} else {
				$serviceIndexes[$row['idReservationService']]['index'] = $currServIdx;
				$serviceIndexes[$row['idReservationService']]['component'] = 1;
				$currServIdx++;
			}
			$this->invoiceRows[$id]['serviceIndex'] = $serviceIndexes[$row['idReservationService']]['index'].'.'.$serviceIndexes[$row['idReservationService']]['component'];

			$ei = [];
			// set row type
			$ei['rowType'] = $row['rowType'];

			// set itinerary airport
			if ($this->tableColumns['itineraryAirports']) {
				$ei['itineraryAirports'] = \Entity\Service::select($row['idReservationService'])->chosenOffer->itinerary->getFromFormat($itineraryFormat);
			}

			// currency details
			if ($this->tableColumns['currencyDetails']) {
				$ei['currencyDetails'] = $currTypes[$row['currencyType']].' / '.\Engine\DateTime::createFromIsoDate($row['currencyDate'])->formatDateStd();
			}
			// unitPrice
			$ei['unitPrice'] = $row['unitPricePrintValue'];
			// unitPriceWithVat
			$ei['unitPriceWithVat'] = ($row['pricePrintValue'] + $row['vatPrintValue']) / $row['quantity'];
			// unit price default currency
			$ei['unitPriceDefCurr'] = \App\CurrencyExchange\Rates::getInstance($invDate)->convert($row['unitPricePrintValue'], $invCurrency, $CFG['currencies']['defaultCurrency']);
			// unit price work currency
			$ei['unitPriceWorkCurr'] = \App\CurrencyExchange\Rates::getInstance($invDate)->convert($row['unitPricePrintValue'], $invCurrency, $CFG['currencies']['workCurrency']);
			// value
			$ei['value'] = $row['pricePrintValue'];
			// value in default currency
			$ei['valueDefCurr'] = \App\CurrencyExchange\Rates::getInstance($invDate)->convert($row['pricePrintValue'], $invCurrency, $CFG['currencies']['defaultCurrency']);
			// value in work currency
			$ei['valueWorkCurr'] = \App\CurrencyExchange\Rates::getInstance($invDate)->convert($row['pricePrintValue'], $invCurrency, $CFG['currencies']['workCurrency']);
			// vat base
			if ($this->tableColumns['vatBase']) {
				$ei['vatBase'] = \Entity\InvoiceRow::select($id)->vatBasePrintValue;
				if ($row['childrenRows']) {
					foreach($row['childrenRows'] as $r) {
					    $ei['vatBase'] += \Entity\InvoiceRow::select($r)->vatBasePrintValue;
					}
				}
			}
			// vat
			$ei['vat'] = $row['vatPrintValue'];
			// vat text
			$ei['vatText'] = $row['vatText'];
			// vat remark
			if ($this->tableColumns['vatRemark'] || $this->tableColumns['vatRemarkOrValue']) {
				$vatRemarks = [];
				$rowObj = \Entity\InvoiceRow::select($id);
				// add current row vat remark
				$vatCfgObj = \App\Config\Services_Calculations_InvoiceVat::getInstance()->getCalculationDetails($rowObj->serviceCode, $rowObj->locationCode, $rowObj->calculationTypeCode);
				if ($vatCfgObj[$rowObj->rowTypeCode]['vatRemark']) {
				    $vatRemarks[$vatCfgObj[$rowObj->rowTypeCode]['vatRemark']] = true;
				}
				else {
				    $vatRemarks[''] = true;
				}
				// add children rows
				if ($row['childrenRows']) {
					foreach($row['childrenRows'] as $idRow) {
						$rowObj = \Entity\InvoiceRow::select($idRow);
						$vatCfgObj = \App\Config\Services_Calculations_InvoiceVat::getInstance()->getCalculationDetails($rowObj->serviceCode, $rowObj->locationCode, $rowObj->calculationTypeCode);
						$vatRemarks[$vatCfgObj[$rowObj->rowTypeCode]['vatRemark']] = true;
					}
				}
				// if one remark found - display it; otherwise set blank
				if (count($vatRemarks) == 1) {
					$ei['vatRemark'] = key($vatRemarks);
				} else {
					$ei['vatRemark'] = '';
				}

			}
			// vatTextOrValue
			if ($this->tableColumns['vatTextOrValue']) {
			    if ($row['vatPrintValue']) {
				    $ei['vatTextOrValue'] = $row['vatPrintValue'];
			    }
			    else {
				    $ei['vatTextOrValue'] = $row['vatText'].' '; // force it as 'string'
			    }
			}
			// vatRemarkOrValue
			if ($this->tableColumns['vatRemarkOrValue']) {
			    if ($row['vatPrintValue']) {
				    $ei['vatRemarkOrValue'] = $row['vatPrintValue'];
			    }
			    else {
			        $ei['vatRemarkOrValue'] = $ei['vatRemark'].' '; // force it as 'string'
			    }
			}
			// total
			$ei['total'] = $row['pricePrintValue'] + $row['vatPrintValue'];
			// totalDefCurr
			if ($this->tableColumns['totalDefCurr']) {
				$ei['totalDefCurr'] = \App\CurrencyExchange\Rates::getInstance($invDate)->convert($ei['total'], $invCurrency, $CFG['currencies']['defaultCurrency']);
			}
			// totalWorkCurr
			if ($this->tableColumns['totalWorkCurr']) {
				$ei['totalWorkCurr'] = \App\CurrencyExchange\Rates::getInstance($invDate)->convert($ei['total'], $invCurrency, $CFG['currencies']['workCurrency']);
			}
			// rowCurrDetExchRate
			if ($this->tableColumns['rowCurrDetExchRate']) {
				$ei['rowCurrDetExchRate'] = \App\CurrencyExchange\Rates::getInstance($row['currencyDate'], $row['currencyType'])->convert(1, $invCurrency, $CFG['currencies']['defaultCurrency'], null);
			}
			// valueDefCurrRowCurrDet
			$ei['valueDefCurrRowCurrDet'] = \App\CurrencyExchange\Rates::getInstance($row['currencyDate'], $row['currencyType'])->convert( $row['pricePrintValue'], $invCurrency, $CFG['currencies']['defaultCurrency']);
			// vatDefCurrRowCurrDet
			$ei['vatDefCurrRowCurrDet'] = \App\CurrencyExchange\Rates::getInstance($row['currencyDate'], $row['currencyType'])->convert( $row['vatPrintValue'], $invCurrency, $CFG['currencies']['defaultCurrency']);
			// totalDefCurrRowCurrDet
			$ei['totalDefCurrRowCurrDet'] = $ei['valueDefCurrRowCurrDet'] + $ei['vatDefCurrRowCurrDet'];

			// associate
			$this->invoiceRowsExtraInfo[$id] = $ei;

		}

		// DETERMINE AND STORE THE TABLE TOTALS ///////////////////////////////////////////////////
		// the columns that will have totals calculated
		$totals = [];

		foreach($this->invoiceRowsExtraInfo as $row) {
			foreach($this->totalCols as $col) {
			    if (is_numeric($row[$col])){
				    $totals[$col] += $row[$col];
			    }
			}
		}

		$totals['vatTextOrValue'] = $totals['vatRemarkOrValue'] = $totals['vat'];
		$this->invoiceTotals = $totals;

	}

	/**
	 * Populates the table rows into the special object table.
	 */
	protected function invoiceStandardTable_populateTableRows()
	{

		$invCurrency=\Entity\Invoice::select($this->idPivot)->currency;

		$rows = [];
		$idx = 0;
		foreach($this->invoiceRows as $id=>$row) {
			// extra info for this row
			$ei=$this->invoiceRowsExtraInfo[$id];

			$idx++;
			$row = [
				'currentNumber' => ['content'=>$idx],
				'serviceIndex' => ['content'=>$row['serviceIndex']],
				'description' => ['content'=>$row['description']],
				'itineraryAirports' => ['content'=>$ei['itineraryAirports']],
				'currencyDetails' => ['content'=>$ei['currencyDetails']],
				'measureUnit' => ['content'=>$row['measureUnit']],
				'quantity' => ['content'=>$row['quantity']],
				'unitPrice' => ['content'=>$ei['unitPrice'], 'type'=>'price'],
				'unitPriceWithVat' => ['content'=>$ei['unitPriceWithVat'], 'type'=>'price'],
				'unitPriceDefCurr' => ['content'=>$ei['unitPriceDefCurr'], 'type'=>'price'],
				'unitPriceWorkCurr' => ['content'=>$ei['unitPriceWorkCurr'], 'type'=>'price'],
				'value' => ['content' => $ei['value'], 'type' => 'price'],
				'valueDefCurr' => ['content' => $ei['valueDefCurr'], 'type' => 'price'],
				'valueWorkCurr' => ['content' => $ei['valueWorkCurr'], 'type' => 'price'],
				'vatBase' => ['content' => $ei['vatBase'], 'type' => 'price'],
				'vat' => ['content' => $ei['vat'], 'type' => 'price'],
				'vatText' => ['content' => $ei['vatText']],
				'vatRemark' => ['content' => $ei['vatRemark']],
				'vatTextOrValue' => ['content' => $ei['vatTextOrValue'], 'type' => 'price'],
				'vatRemarkOrValue' => ['content' => $ei['vatRemarkOrValue'], 'type' => 'price'],
				'total' => ['content' => $ei['total'], 'type' => 'price'],
				'currency' => ['content' => $invCurrency],
				'totalDefCurr' => ['content' => $ei['totalDefCurr'], 'type' => 'price'],
				'totalWorkCurr' => ['content' => $ei['totalWorkCurr'], 'type' => 'price'],
				'rowCurrDetExchRate' => ['content' => $ei['rowCurrDetExchRate']],
				'valueDefCurrRowCurrDet' => ['content' => $ei['valueDefCurrRowCurrDet'], 'type' => 'price'],
				'vatDefCurrRowCurrDet' => ['content' => $ei['vatDefCurrRowCurrDet'], 'type' =>'price'],
				'totalDefCurrRowCurrDet' => ['content' => $ei['totalDefCurrRowCurrDet'], 'type' => 'price'],
				'fakeColumn1' => ['content' => (String)$this->settings['column_fakeColumn1Content']],
				'fakeColumn2' => ['content' => (String)$this->settings['column_fakeColumn2Content']],
				'fakeColumn3' => ['content' => (String)$this->settings['column_fakeColumn3Content']],
				'fakeColumn4' => ['content' => (String)$this->settings['column_fakeColumn4Content']],
				'fakeColumn5' => ['content' => (String)$this->settings['column_fakeColumn5Content']],
				'fakeColumn6' => ['content' => (String)$this->settings['column_fakeColumn6Content']],
			];
			// associate this row
			$rows[$id] = $row;

		}

		// ASSOCIATE ALL INVOICE ROWS /////////////////////////////////////////////////////////////
		$this->tableRows = $rows;

	}



	/**
	 * Defines the table footer (the totals row).
	 */
	protected function render_table_addTableFoot()
	{

		global $CFG;

		// check input - only if the linear totals was selected
		if ($this->settings['totalsType']!='linear')
		    return ;

		// the totals row
		$finalRow = new \DTMControl_table_tr();

		// SCAN ROWS AND DETERMINE THE TOTALS VALUES //////////////////////////////////////////////
		// determine the first cell colspan value
		$firstCellColspan = 0;
		foreach($this->tableColumns as $col=>$nothing) {
			if ($this->invoiceTotals[$col]) break;
			$firstCellColspan++;
		}

		// DISPLAY FIRST CELL /////////////////////////////////////////////////////////////////////
		if ($firstCellColspan) {
			$finalRow->add_td(
				[
					'fontFamily' => $this->settings['column_finalRowFont'],
					'style_bold' => (bool)$this->settings['column_finalRowTextStyle']['bold'],
					'style_italic' => (bool)$this->settings['column_finalRowTextStyle']['italic'],
					'style_underline' => (bool)$this->settings['column_finalRowTextStyle']['underline'],
					'fontSize' => $this->settings['column_finalRowFontSize'],
					'color' => $this->settings['column_finalRowTextColor'],
					'backgroundColor' => $this->settings['column_finalRowBackgroundColor'],
					'text' => $this->settings['column_finalRowText'],
					'colspan' => $firstCellColspan,
					'align' => "right",
				]
			);
		}

		// DISPLAY THE REST OF THE CELLS //////////////////////////////////////////////////////////
		$idx = 0;
		foreach($this->tableColumns as $col=>$nothing) {
			// skip the first $firstCellColspan cells
			$idx++;
			if ($idx <= $firstCellColspan) continue;

			// determine the cell content
			if ($this->invoiceTotals[$col]) {
				// add the value
				$cellContent = $this->formatAsPrice($this->invoiceTotals[$col]);
				// add currency
				if ($this->settings['totalsShowCurrency']['yes']) {
					// local alphabet
					if ($this->settings['totalCurrencyAlphabet'] == 'local') {
						$currCfg = \App\Config\Currencies::getInstance()->getAll();
						if ($col == "totalWorkCurr" || $col == "valueWorkCurr"){
						    $cellContent .= ' ' . $currCfg[$CFG['currencies']['workCurrency']]['currencyName2'];
						}
						elseif ($col == "totalDefCurr" || $col=="valueDefCurr" || $col == 'valueDefCurrRowCurrDet' || $col == 'vatDefCurrRowCurrDet' || $col == 'totalDefCurrRowCurrDet') {
						  $cellContent.=' '.$currCfg[$CFG['currencies']['defaultCurrency']]['currencyName2'];
						}
						else {
						    $cellContent .= ' ' . $currCfg[ \Entity\Invoice::select($this->idPivot)->currency ]['currencyName2'];
						}
					}
					// standard alphabet
					else {
					    if ($col == "totalWorkCurr" || $col == "valueWorkCurr") {
						    $cellContent.=' '.$CFG['currencies']['workCurrency'];
					    }
					    elseif ($col == "totalDefCurr" || $col == "valueDefCurr" || $col == 'valueDefCurrRowCurrDet' || $col == 'vatDefCurrRowCurrDet' || $col == 'totalDefCurrRowCurrDet') {
						  $cellContent.=' '.$CFG['currencies']['defaultCurrency'];
					    }
					    else {
						    $cellContent.=' '.\Entity\Invoice::select($this->idPivot)->currency;
					    }
					}
				}
			} else {
				$cellContent = '';
			}

			// add cell with its properties
			$finalRow->add_td(
				[
					'fontFamily' => $this->settings['column_finalRowFont'],
					'style_bold' => (bool)$this->settings['column_finalRowTextStyle']['bold'],
					'style_italic' => (bool)$this->settings['column_finalRowTextStyle']['italic'],
					'style_underline' => (bool)$this->settings['column_finalRowTextStyle']['underline'],
					'fontSize' => $this->settings['column_finalRowFontSize'],
					'color' => $this->settings['column_finalRowTextColor'],
					'backgroundColor' => $this->settings['column_finalRowBackgroundColor'],
					'text' => $cellContent,
					'align' => $this->settings['totalsAlignment'],
				]
			);

		}

		$this->table->add_tr($finalRow);

	}

}

