<?php
namespace App\ClientCollection\Corporate\Document;

/**
 * This class creates and generates the xlsx email attachment
 * @author Laura
 *
 */
abstract class XlsxAbstract extends GeneralAbstract
{

	/**
	 * The attached file name.
	 * @var string
	 */
	protected $attachmentFileName = '';

	/**
	 * The sheet name.
	 * @var string
	 */
	protected $sheetName = '';

	/**
	 * The columns list and their style
	 * @var array
	 */
	protected $columns = [];

	/**
	 * The general row style
	 * @var string
	 */
	protected $rowStyle = '';

	/**
	 * Contains the overdue invoices rows that will be exported
	 * @var array
	 */
	private $overdueRowsList = [];

	/**
	 * Contains the due in days invoices rows that will be exported
	 * @var array
	 */
	private $dueInDaysRowsList = [];

	/**
	 * Populate the content of the report file.
	 */
	public function populateReport() : void
	{
	    $this->loadLang();

		$writer = new \OpenSpout\Writer\XLSX\Writer();
		$writer->openToFile($this->tempFileFullPath);

		$writer->getCurrentSheet()->setName($this->sheetName);
		$writer->getCurrentSheet()->setColumnWidthForRange(20, 1, count($this->columns));

		$this->populateReportData();

		if ($this->overdueRowsList) {
		    $this->addHeader($writer);

		    foreach ($this->overdueRowsList as $row) {
		        // order the cells by the columns list - if we have something set
		        if (array_filter($row)) {
    		        $row = array_replace(array_flip(array_keys($this->columns)), $row);
		        }

    		    // style cells
    		    $formattedCells = [];
    		    foreach ($row as $key => $cell) {
    		        if (isset($cell['style'])) {
    		            $formattedCells[] = \OpenSpout\Common\Entity\Cell::fromValue($cell['value'], $this->getStyle($cell['style']));
    		        }
    		        else {
    		            $formattedCells[] = \OpenSpout\Common\Entity\Cell::fromValue($cell, $this->getStyle($this->columns[$key]));
    		        }
    		    }

    		    $rowObj = new \OpenSpout\Common\Entity\Row($formattedCells);
    		    $rowObj->setStyle($this->getStyle($this->rowStyle));
    		    $writer->addRow($rowObj);
    		}
		}

		if ($this->dueInDaysRowsList) {
		    $this->addHeader($writer);

		    foreach ($this->dueInDaysRowsList as $row) {
		        // order the cells by the columns list - if we have something set
		        if (array_filter($row)) {
		            $row = array_replace(array_flip(array_keys($this->columns)), $row);
		        }

		        // style cells
		        $formattedCells = [];
		        foreach ($row as $key => $cell) {
		            if (isset($cell['style'])) {
		                $formattedCells[] = \OpenSpout\Common\Entity\Cell::fromValue($cell['value'], $this->getStyle($cell['style']));
		            }
		            else {
		                $formattedCells[] = \OpenSpout\Common\Entity\Cell::fromValue($cell, $this->getStyle($this->columns[$key]));
		            }
		        }

		        $rowObj = new \OpenSpout\Common\Entity\Row($formattedCells);
		        $rowObj->setStyle($this->getStyle($this->rowStyle));
		        $writer->addRow($rowObj);
		    }
		}

		$writer->close();
	}

	/**
	 * Add table header
	 */
	protected function addHeader(\OpenSpout\Writer\XLSX\Writer $writer) : void
	{

		// populate header
		$headerCells = [];
		foreach ($this->columns as $column => $columnType) {
			$headerCells[] = \OpenSpout\Common\Entity\Cell::fromValue($this->getColumnName($column), $this->getStyle('header'));
		}
		$row = new \OpenSpout\Common\Entity\Row($headerCells, $this->getStyle('header'));

		$writer->addRow($row);
	}

	/**
	 * Loads the local lang associated to each template
	 */
	abstract protected function loadLang() : void;

	/**
	 * Returns the translated column name
	 * @return string
	 */
	abstract protected function getColumnName($columnCode) : string;

	/**
	 * Populates the rows that will be exported
	 * @return array
	 */
	abstract protected function populateReportData() : void;

	/**
	 * Exports the rows one by one
	 * @param array $row
	 */
	protected function exportRow(array $row, string $type) : void
	{
	    if ($type == 'overdue') {
	        $this->overdueRowsList[] = $row;
	    }
	    else {
	        $this->dueInDaysRowsList[] = $row;
	    }
	}

	/**
	 * Returns the style object
	 * @param string $styleName
	 * @return \OpenSpout\Common\Entity\Style\Style
	 */
	protected function getStyle(string $styleName) : \OpenSpout\Common\Entity\Style\Style
	{
	    $styleObj = new \OpenSpout\Common\Entity\Style\Style();
	    $styleObj
	    ->setShouldWrapText(false)
	    ->setFontSize(9)
	    ->setFontName("Arial")
	    ->setBorder(
	        new \OpenSpout\Common\Entity\Style\Border(
	            new \OpenSpout\Common\Entity\Style\BorderPart(
	                \OpenSpout\Common\Entity\Style\Border::BOTTOM,
	                \OpenSpout\Common\Entity\Style\Color::BLACK,
	                \OpenSpout\Common\Entity\Style\Border::WIDTH_THIN,
	                \OpenSpout\Common\Entity\Style\Border::STYLE_SOLID
	                )
	            )
	        );

	    switch ($styleName)
	    {
	        case 'numeric':
	            $styleObj
	                ->setCellAlignment(\OpenSpout\Common\Entity\Style\CellAlignment::RIGHT);
	            break;

	        case 'price':
	            $styleObj
    	            ->setFormat('0.00')
    	            ->setCellAlignment(\OpenSpout\Common\Entity\Style\CellAlignment::RIGHT);
	            break;

	        case 'statusOverdue':
	            $styleObj
    	            ->setCellAlignment(\OpenSpout\Common\Entity\Style\CellAlignment::LEFT)
    	            ->setFontColor(\OpenSpout\Common\Entity\Style\Color::RED)
    	            ->setFontBold();
	            break;

	        case 'date':
	            $styleObj
	                ->setCellAlignment(\OpenSpout\Common\Entity\Style\CellAlignment::RIGHT);
	            break;

	        case 'header': case 'footer':
	            $styleObj
    	            ->setFontBold()
    	            ->setCellAlignment(\OpenSpout\Common\Entity\Style\CellAlignment::LEFT);
	            break;

	        case 'status':
	            $styleObj
	            ->setCellAlignment(\OpenSpout\Common\Entity\Style\CellAlignment::LEFT)
	            ->setFontBold();
	            break;

	        case 'default':
	            break;
	    }

	    return $styleObj;
	}
}