<?php
namespace Modules\Admin\ImportEntities;

class Controller extends \App\Mvc\Controller\Form\WindowAbstract
{

	/**
	 * for every step is a dfferent form and each step has different actions
	 * @var int
	 */
	protected $step = 1;

	/**
	 * (non-PHPdoc)
	 * @see \App\Mvc\Controller\Window\PaginatedListing\PaginatedListing::initialize()
	 */
	protected function initialize()
	{
		parent::initialize();
		$this->actionsCfg['reset'] =     	['checkSection' => true, 'checkOption' => false,];
		$this->actionsCfg['download'] =		['checkSection' => true, 'checkOption' => false,];
	}


	/**
	 * (non-PHPdoc)
	 * @see \App\Mvc\Controller\Form\WindowAbstract::getDefaultFormData()
	 */
	protected function getDefaultFormData($R)
	{
		$formData['step'] 			= 1;

		return $formData;
	}

	/**
	 * (non-PHPdoc)
	 * @see \App\Mvc\Controller\Form\WindowAbstract::getSubmitFormData()
	 */
	protected function getSubmitFormData($R, \App\MessagesCollector $msgs)
	{

		$CFG = \Engine\Loader_Cfg::getInstance()->getGlobal();
		$filePath = $CFG['paths']['temporary'].'importEntities/';
		$formData = $R;

		// make sure that the subdir in temporary is created
		\Engine\Dir::create($filePath);


		// STEP 1
		// add the file, the csv delimiter and the type of entity that will be imported
		if ($R['step'] == 1) {

			try {

				$this->checkFirstStep($R);

				// import model
				$entity = $R['fileType'];
				$entityName 	= sprintf("\Modules\Admin\ImportEntities\Model\Import\%s", $entity);
				$importModel 	= new $entityName([]);

				// parse the file
				$parser 	= new \Modules\Admin\ImportEntities\Model\FileParser\Csv($filePath.CURRENT_ID_USER.".csv");
				$parser->delimiter = $R['csvDelimiter'];
				$parser->setColumns($importModel->getEntityFields());

				$importModel->setFileContent($parser->getFileContent());

				$existingColumnsArr = $parser->getExistingColumns();
				$existingColumns = null;
				if ($existingColumnsArr) {
					$existingColumns = implode(', ', $existingColumnsArr);
				}

				$missingColumnsArr = array_diff($importModel->getEntityFields(), $existingColumnsArr);
				$missingColumns = $missingColumnsArr ? implode(', ', $missingColumnsArr) : '';

				if ($importModel->useDateFormat()) {
					$importModel->setDateFormat($R['dateFormat']);
				}

				$contentInfo = $importModel->analyze();

				// save information in storage
				$storage = [
					'csvDelimiter' 			=> $R['csvDelimiter'],
					'file' 					=> [
						'fileWithPath' 		=> $filePath.CURRENT_ID_USER.".csv",
						'fileSize' 			=> \Engine\File::formatBytes( filesize($filePath.CURRENT_ID_USER.".csv") ),
						'lines' 			=> count($parser->getFileContent()),
						'existingColumns'	=> $existingColumns,
						'missingColumns'	=> $missingColumns,
						'contentInfo' 		=> $contentInfo,
					],
					$entity 				=> $R[$entity],
					'dateFormat'			=> $R['dateFormat'],
				];
				$key = "\Modules\Admin\ImportEntities:".CURRENT_ID_USER;
				\Engine\Storage\General::getInstance('session')->set($key, $storage);

				// step
				$this->step = 2;

				// formData
				$formData['fileType'] 	= $R['fileType'];
				$formData['step'] 		= $this->step;

			}
			catch (\App\MessagesException $ex) {
				$msgs->appendMessages($ex->getMessagesCollector());
			}
		}
		// STEP 2
		elseif ($R['step']==2)
		{
			// formData
			$formData['fileType'] 	= $R['fileType'];
			$formData['step'] 		= $this->step;

		}

		else {
			$formData = [];
			$this->step = 1;
		}

		return $formData;
	}

	/**
	 * (non-PHPdoc)
	 * @see \App\Mvc\Controller\Form\WindowAbstract::processFormData()
	 */
	protected function processFormData(Array $R, \App\MessagesCollector $msgs)
	{

		set_time_limit(0);

		$CFG = \Engine\Loader_Cfg::getInstance()->getGlobal();
		$messagesFromImport = null;

		if ($R['step'] == 2) {
			// check if exists a file
			$fileWithPath = sprintf('%simportEntities/%s.csv', $CFG['paths']['temporary'], CURRENT_ID_USER);
			if (!\Engine\File::check($fileWithPath)) {
				$msgs->addError($this->lang['index']['messages']['noFile']);
				$this->step = 1;
			}

			if ($R['confirmImport'] and !$msgs->hasErrorOrWarning()) {
				$storage = \Engine\Storage\General::getInstance('session')->get("\Modules\Admin\ImportEntities:".CURRENT_ID_USER);

				// import model
				$entityName 	= sprintf("\Modules\Admin\ImportEntities\Model\Import\%s", $R['fileType']);

				$parser 	= new \Modules\Admin\ImportEntities\Model\FileParser\Csv($fileWithPath);
				$parser->delimiter = $storage['csvDelimiter'];
				$fileData 	= $parser->getFileContent();

				// htmlClean all csv rows
				if (!in_array($R['fileType'], ['ImportedServicesInsert', 'ImportedServicesUpdate', 'ImportedDocumentsInsert'])) {
					$fileData = cleanHtmlRequestVars($fileData);
				}

				$importModel = new $entityName();
				$importModel->setFileContent($fileData);

				if ($R['fileType'] == 'ImportedServicesInsert') {
					$importModel->setPassengersFormat($storage['ImportedServicesInsert']['passengersFormat']);
				}
				if ($importModel->useDateFormat()) {
					$importModel->setDateFormat($storage['dateFormat']);
				}
				$messagesFromImport = $importModel->process();

				$output = new \Modules\Admin\ImportEntities\Model\MessagesCollectorExport($messagesFromImport);
				$logFileName = sprintf("ImportEntities_%s", \Engine\DateTime::create()->formatDatetimeIso());
				\Engine\File::create($CFG['paths']['temporary']."importEntities/$logFileName.csv", $output->getCsvContent());

				if ($messagesFromImport->hasErrorOrWarning()) {
					\Log::getInstance()->warning(sprintf("[%s] some errors occured while importing entities", __METHOD__), [
						'file' => new \Engine\Logger\Context\File([
							'name'=> 'log',
							'content' => $output->getCsvContent(),
						]),
					]);
				}
				else {
					\Log::getInstance()->info(sprintf("[%s] entities were imported with success", __METHOD__), [
						'file' => new \Engine\Logger\Context\File([
							'name'=> 'log',
							'content' => $output->getCsvContent(),
						]),
					]);
					\Engine\File::delete($fileWithPath);
				}

				if ($messagesFromImport->hasErrorOrWarning()) {
					$msgs->addWarning($this->lang['index']['messages']['error']);
				}
				else {
					$msgs->addSuccess($this->lang['index']['messages']['success']);
				}


				$this->step = 1;
				$this->actionReset();
			}
			else {
				$msgs->addWarning($this->lang['index']['messages']['confirmIsMandatory']);
				$this->step = 2;
			}
		}
	}

	/**
	 * check the input from the first step
	 * @param array $R
	 * @param \App\MessagesCollector $msgs
	 */
	protected function checkFirstStep(Array $R)
	{

		$messagesCollector = new \App\MessagesCollector();

		// load the configs
		$CFG = \Engine\Loader_Cfg::getInstance()->getGlobal();

		$uploadedFile = new \App\Form\UploadedFiles\File('file');

		// check uploaded file
		if (!$uploadedFile->hasValidFile()) {
			$messagesCollector->addWarning($this->lang['index']['messages']['noFile']);
		}
		elseif (!$uploadedFile->getSize()) {
			$messagesCollector->addWarning($this->lang['index']['messages']['emptyFile']);
		}
		// actually save the file on disk
		else {
			try {
				$uploadedFile->moveUploadedFile( $CFG['paths']['temporary']."importEntities/" . CURRENT_ID_USER . '.csv');
			} catch (\RuntimeException $e) {
				$messagesCollector->addError($e->getMessage());
			}
		}

		// check csv delimiter
		if (!$R['csvDelimiter']) {
			$messagesCollector->addWarning($this->lang['index']['messages']['noCsvDelimiter']);
		}

		// file type
		if (!$R['fileType']) {
			$messagesCollector->addWarning($this->lang['index']['messages']['noFileType']);
		}

		// check the date format
		if (in_array($R['fileType'], ['ContactPersonsInsert', 'ImportedDocumentsInsert', 'PassengersInsert', 'ImportedServicesInsert', 'SupplierInvoicesInsert'])) {
			if (!$R['dateFormat']) {
				$messagesCollector->addWarning($this->lang['index']['messages']['noDateFormat']);
			}
			elseif (!in_array($R['dateFormat'], $this->cfg['dateFormat'])) {
				$messagesCollector->addWarning($this->lang['index']['messages']['dateFormatInvalid']);
			}
		}

		// services and passengers format
		if ($R['fileType'] == 'ImportedServicesInsert' and !$R['ImportedServicesInsert']['passengersFormat']) {
			$messagesCollector->addWarning($this->lang['index']['messages']['noPassengersFormat']);
		}

		// CHECK OPENING BALANCES STUFF ///////////////////////////////////////////////////////////
		if ($R['fileType'] == 'OpeningBalances') {
			// check responsible user
			if (!$R['OpeningBalances']['responsibleUser']['id']) {
				$messagesCollector->addWarning($this->lang['index']['messages']['openingBalances']['noRespUser']);
			}
			// check order type
			if (!$R['OpeningBalances']['orderType'] and \App\Config\OrderTypes::getInstance()->getMandatory()) {
				$messagesCollector->addWarning($this->lang['index']['messages']['openingBalances']['noOrderType']);
			}
			// check order services type
			if (!$R['OpeningBalances']['orderServicesType'] and \App\Config\OrderServicesTypes::getInstance()->getMandatory()) {
				$messagesCollector->addWarning($this->lang['index']['messages']['openingBalances']['noOrderServicesType']);
			}
			// check order flag
			if (!$R['OpeningBalances']['orderFlag'] and \App\Config\OrderFlags::getInstance()->getMandatory()) {
				$messagesCollector->addWarning($this->lang['index']['messages']['openingBalances']['noOrderFlag']);
			}
			// check service type
			if (!$R['OpeningBalances']['serviceCode']) {
				$messagesCollector->addWarning($this->lang['index']['messages']['openingBalances']['noServiceCode']);
			}
			// check offer supplier
			if (!$R['OpeningBalances']['offerSupplier']['id']) {
				$messagesCollector->addWarning($this->lang['index']['messages']['openingBalances']['noOffSupplier']);
			}
			// check issue doc type
			if (!$R['OpeningBalances']['issueDocType']) {
				$messagesCollector->addWarning($this->lang['index']['messages']['openingBalances']['noIssueDocType']);
			}
			// check invoice doc template
			if (!$R['OpeningBalances']['idDocTemplate']) {
				$messagesCollector->addWarning($this->lang['index']['messages']['openingBalances']['noDocTemplate']);
			}

			if ($R['csvDelimiter']) {
				$filePath = $CFG['paths']['temporary']."importEntities/".CURRENT_ID_USER.".csv";
				$parser = new \Modules\Admin\ImportEntities\Model\FileParser\Csv($filePath);
				$parser->delimiter = $R['csvDelimiter'];
				$fileData = $parser->getFileContent();

				$importModel = new \Modules\Admin\ImportEntities\Model\Import\OpeningBalances();
				$importModel->setFileContent($fileData);
				$importModel->setDateFormat($R['dateFormat']);

				if ($R['dateFormat']) {
					$importModel->checkContent($messagesCollector);
				}
			}

		}

		if ($messagesCollector->hasErrorOrWarning()) {
			throw new \App\MessagesException($messagesCollector);
		}
	}


	/**
	 * Delete the file and empty the storage
	 */
	public function actionReset()
	{
		// load the configs
		$CFG = \Engine\Loader_Cfg::getInstance()->getGlobal();

		// clear storage
		\Engine\Storage\General::getInstance('session')->delete("\Modules\Admin\ImportEntities:".CURRENT_ID_USER);

		// delete file
		$fileWithPath = sprintf('%simportEntities/%s.csv', $CFG['paths']['temporary'], CURRENT_ID_USER);
		\Engine\File::delete($fileWithPath);

		// redirect to import entities section
		$response = new \Engine\Mvc\Response\HtmlRedirect(\Engine\Mvc\Dispatcher::getInstance()->getAppUrl("Modules/Admin/ImportEntities", "", []));

		return $response;
	}


	/**
	 * Download a csv with the header
	 * @param array $R
	 */
	public function actionDownload($R)
	{

		if (!$R['entity']) {
			return null;
		}

		$entityClass 	= sprintf("\Modules\Admin\ImportEntities\Model\Import\%s", $R['entity']);
		$importModel 	= new $entityClass();
		$columns 		= $importModel->getEntityFields();

		$response = new \Engine\Mvc\Response\FileDownload(implode(',', $columns));
		$response->setFilename(sprintf("%s.csv", $R['entity']));

		return $response;
	}
}