<?php
namespace Modules\Orders\Sabre\Collector;

class Model extends \ModulesAbstract\ImportedOrdersFileManager\Model
{
	/**
	 * (non-PHPdoc)
	 * @see \ModulesAbstract\ImportedOrdersFileManager\Model::createConvertInputToFilters()
	 */
	public function createConvertInputToFilters()
	{
		return new \Modules\Orders\Sabre\Collector\Model\ConvertInputToFilters();
	}

	/**
	 * (non-PHPdoc)
	 * @see \ModulesAbstract\ImportedOrdersFileManager\Model::getFileParsedData()
	 */
	public function getFileParsedData($fileFullPath)
	{
		$fileParser = $this->buildFileParser($fileFullPath);
		return [
			'extractedData' => 	$fileParser->getExtractedData(),
			'fileId' =>			$fileParser->getFileId(),
			'messages' =>		$fileParser->getMessagesCollector(), // TODO: [cleanMsgs-gdsMsgs] confirmat Lucian
		];
	}

	/**
	 * Build file parser object
	 * @param String $fileFullPath
	 * @return \App\Sabre\FileParser\IUR
	 */
	private function buildFileParser($fileFullPath)
	{
		$fileParser = new \App\Sabre\FileParser\IUR();
		$fileParser->setMessagesCollector(new \App\MessagesCollector());
		$fileParser->setRawData(\Engine\File::getContents($fileFullPath));
		$fileParser->setStoredData('fileDate', min($fileParser->collectFileDatesFromPath($fileFullPath)));

		// exceptions might get thrown in the following few lines
		$fileParser->extract();

		return $fileParser;
	}

	/**
	 * (non-PHPdoc)
	 * @see \ModulesAbstract\ImportedOrdersFileManager\Model::getStructureParserData()
	 */
	public function getStructureParserData($fileFullPath)
	{
		$processor = $this->buildStructureParser($fileFullPath);

		return [
			'transactions' => 			$processor->getSortedTransactions(),
			'messages' =>				$processor->getMessagesCollector(), // TODO: [cleanMsgs-gdsMsgs] confirmat Lucian
			'fileId' =>					$processor->getFileParser()->getFileId(),
			'fileParserMessages' =>		$processor->getFileParser()->getMessagesCollector(), // TODO: [cleanMsgs-gdsMsgs] confirmat Lucian
			'generalAssociations'=> 	$processor->getInternalAssociations(),
		];
	}

	private function buildStructureParser($fileFullPath)
	{
		$fileParser = $this->buildFileParser($fileFullPath);

		// use the processor to process the raw data
		$processor = new \App\Sabre\StructureParser\Processor($fileParser);
		$processor->initialize();
		$processor->setFile($fileFullPath);

		return $processor;
	}

	public function parseFile($fileFullPath)
	{
		$processor = $this->buildStructureParser($fileFullPath);

		// store the parsed data
		$storage = new \App\Sabre\Storage\StorageHandler();
		$storage->setProcessor($processor);
		$storage->setOption('source', "manual");
		$storage->setOption('IP', $_SERVER['REMOTE_ADDR']);
		$ret = $storage->execute();

		// determine what entities were inserted, reselect from DB, and insert them
		$entities = [];
		if ($ret['inserted']) {
			foreach ($ret['inserted'] as $entityId) {
				$entities[] = \Entity\SabreService::select($entityId);
			}

			// plugin trigger
			\Engine\Plugins\Manager::getInstance()->executeEvent('Sabre-beforeConvertingImportedOrder-inCollector', [
				'this' => 		  	$this,
				'entities' => 		$entities,
				'structureParser'=> $processor,
				'storage' => 		$storage,
				'storageOutput' => 	$ret,
			]);

			// filter out documentIssue operations
			$entities = array_filter($entities, function($service) {
				/* @var $service \Entity\SabreService */
				return !(in_array($service->serviceCode, ['documentIssue', ]) && !$service->transactionData->documents->docSubType);
			});

			if ($entities) {
				$convertor = new \App\Sabre\CompatibilityWithImportedOrders\Processor($entities);
				$order = $convertor->getConvertedOrder();
				$applyMode = $convertor->getConvertedApplyMode();

				$orderInsert = \Entity\ImportedOrder::insert();
				$orderInsert->applyMode = $applyMode;	// overwrite, merge
				$orderInsert->order = $order;

				$orderInsert->originalFilesWithPath = [$this->getFilePathRelativeToFilesRoot($fileFullPath)];
				$orderInsert->save();

				$insertedOrderId = $orderInsert->getId();

				// collect a list of affected files, and update their `idImportedOrders` field with the current $insertedOrderId
				// step 1: collect affected files. I'd expect that only one file gets filled in here, but one never knows
				$affectedFiles = [];
				foreach($entities as $ent) {
					$affectedFiles[$ent->idFile] = $ent->file;
				}

				// step 2: update their corresponding field
				foreach($affectedFiles as $file) {
					$fileUpd = \Entity\SabreFile::update($file->getId());
					$idImportedOrders = $file->idImportedOrders;
					$idImportedOrders[] = $insertedOrderId;
					$fileUpd->idImportedOrders = $idImportedOrders;
					$fileUpd->save();
				}

				$processor->getFileParser()->destroyCCInformationAndWriteInto($fileFullPath);
			}
		}
	}
}