<?php
namespace ModulesAbstract\PluginReports\ExtraSupport\ExtractCreditCardDetails;

/**
 * Extract Credit Card details from different sources and return the object
 */
class DefaultExtractor
{

	/**
	 * default Sources - these are the entity types that are available for processing
	 * @var array
	 */
	protected $sources = [
		'offer:formOfPayment:maskedNumber',
		'offer:formOfPayment:originalNumber',
		'offer:formOfCashing:maskedNumber',
		'offer:formOfCashing:originalNumber',
		'importedService:offer:originalNumber',
		'importedService:offer:maskedNumber',
		'relevantImportedService:offer:originalNumber',
		'relevantImportedService:offer:maskedNumber',
		'service:remarks',		// TODO: this should be removed, unused
		'plugin:ccAssoc',		// TODO: this should be removed
		'default'
	];

	/**
	 * Disable Sources - it is used to store entity types that we need to disable from processing
	 * @type array
	 */
	protected $disableSources = [];

	/**
	 * Service Entity
	 * @var \Entity\Service
	 */
	protected $serviceEntity = null;

	/**
	 * Invoice Entity
	 * @var \Entity\Invoice
	 */
	protected $invoiceEntity = null;

	/**
	 * CC associations
	 * @var array
	 */
	protected $ccAssoc = null;

	/**
	 * default credit Card Details
	 * @var CreditCardDetails
	 */
	protected $defaultCcDetails = null;

	/**
	 * Return the sources in order
	 * @return array
	 */
	protected function getSources()
	{
		return $this->sources;
	}

	/**
	 * Set the sources in order
	 * @return DefaultExtractor
	 */
	public function setSources(array $sources)
	{
		$this->sources = $sources;
		return $this;
	}

	/**
	 * Enable Data Source
	 * @param string $source
	 * @return DefaultExtractor
	 */
	public function enableSource(string $source)
	{
		unset($this->disableSources[$source]);
		return $this;
	}

	/**
	 * Disable Data Source
	 * @param string $source
	 * @return DefaultExtractor
	 */
	public function disableSource(string $source)
	{
		$this->disableSources[$source] = true;
		return $this;
	}

	/**
	 * Disable All Data Source
	 * @return DefaultExtractor
	 */
	public function disableAllSources()
	{
		foreach ($this->sources as $source)	{
			$this->disableSources[$source] = true;
		}
		return $this;
	}


	/**
	 * Set the invoice Entity
	 * @param \Entity\Invoice $invoiceEntity
	 * @return DefaultExtractor
	 */
	public function setInvoiceEntity(\Entity\Invoice $invoiceEntity)
	{
		$this->invoiceEntity = $invoiceEntity;
		return $this;
	}

	/**
	 * Set the service Entity
	 * @param \Entity\Service $serviceEntity
	 * @return DefaultExtractor
	 */
	public function setServiceEntity(\Entity\Service $serviceEntity)
	{
		$this->serviceEntity = $serviceEntity;
		return $this;
	}

	/**
	 * Set corporate - CC associations
	 * @param array $ccAssoc
	 * @return \ModulesAbstract\PluginReports\ExtraSupport\ExtractCreditCardDetails\DefaultExtractor
	 */
	public function setCcAssocDetails(Array $ccAssoc)
	{
		$this->ccAssoc = $ccAssoc;
		return $this;
	}

	/**
	 * Set the default CC details object
	 * @param CreditCardDetails $creditCardDefaultDetails
	 * @return DefaultExtractor
	 */
	public function setDefaultDetails(\ModulesAbstract\PluginReports\ExtraSupport\ExtractCreditCardDetails\CreditCardDetails $defaultCcDetails)
	{
		$this->defaultCcDetails = $defaultCcDetails;
		return $this;
	}

	/**
	 * Return the default CC details object
	 * @return CreditCardDetails|NULL
	 */
	protected function get_defaultDetails()
	{
		if ($this->defaultCcDetails) {
			return $this->defaultCcDetails;
		}
		return null;
	}


	/**
	 * Extract CC data from different sources
	 * @return CreditCardDetails|NULL
	 */
	public function extractData()
	{
		if (!$this->sources) {
			// if no source found return cc details with null
			$defaultCcDetails = new \ModulesAbstract\PluginReports\ExtraSupport\ExtractCreditCardDetails\CreditCardDetails();
			return $defaultCcDetails;
		}

		foreach ($this->sources as $source) {

			// if not disabled
			if (!$this->disableSources[$source]) {
				switch ($source) {
					// TODO this should be removed
					case 'service:remarks':
							$data = $this->extract_details_from_serviceRemarks();
							if ($data) {
								return $data;
							}
					break;

					case 'offer:formOfPayment:originalNumber':
						$data = $this->extract_service_offer_formOfPayment_originalNumber();
						if ($data) {
							return $data;
						}
					break;

					case 'offer:formOfPayment:maskedNumber':
						$data = $this->extract_service_offer_formOfPayment_maskedNumber();
						if ($data) {
							return $data;
						}
					break;

					case 'offer:formOfCashing:originalNumber':
						$data = $this->extract_service_offer_formOfCashing_originalNumber();
						if ($data) {
							return $data;
						}
					break;

					case 'offer:formOfCashing:maskedNumber':
						$data = $this->extract_service_offer_formOfCashing_maskedNumber();
						if ($data) {
							return $data;
						}
					break;

					case 'importedService:offer:originalNumber':
						$data = $this->extract_importedService_offer_originalNumber();
						if ($data) {
							return $data;
						}
					break;

					case 'importedService:offer:maskedNumber':
						$data = $this->extract_importedService_offer_maskedNumber();
						if ($data) {
							return $data;
						}
					break;

					case 'relevantImportedService:offer:originalNumber':
						$data = $this->extract_relevantImportedService_offer_originalNumber();
						if ($data) {
							return $data;
						}
					break;

					case 'relevantImportedService:offer:maskedNumber':
						$data = $this->extract_relevantImportedService_offer_maskedNumber();
						if ($data) {
							return $data;
						}
					break;

					// TODO this should be removed
					case 'plugin:ccAssoc':
						$data = $this->extract_from_plugin_ccAssociations();
						if ($data) {
							return $data;
						}
					break;

					case 'default':
						$data = $this->get_defaultDetails();
						if ($data) {
							return $data;
						}
					break;

					// the source is not valid
					default: {
						throw new \Exception("The source '$source' is not valid.");
					}
				}
			}
		}

		return null;
	}

	/**
	 * // TODO this should be removed
	 * Extracts CC details from service remarks else return null
	 * @type mixed
	 * @return CreditCardDetails|NULL
	 */
	protected function extract_details_from_serviceRemarks()
	{
		if ($this->serviceEntity->processedRemarks['CREDIT_CARD_NUMBER']) {
			$creditCardDetails = new \ModulesAbstract\PluginReports\ExtraSupport\ExtractCreditCardDetails\CreditCardDetails();
			$creditCardDetails->number = 			$this->serviceEntity->processedRemarks['CREDIT_CARD_NUMBER'];
			$creditCardDetails->expireDate = 		$this->serviceEntity->processedRemarks['CREDIT_CARD_EXPIRY_DATE'];
			$creditCardDetails->approvalCode = 		$this->serviceEntity->processedRemarks['CREDIT_CARD_APPROVAL_CODE'];
			$creditCardDetails->company = 			$this->serviceEntity->processedRemarks['CREDIT_CARD_COMPANY'];
			$creditCardDetails->ccDataSource = 		__FUNCTION__;
			return $creditCardDetails;
		}
		return null;
	}

	protected function extract_service_offer_formOfPayment_originalNumber()
	{
		if ($this->serviceEntity->recordExists()) {
			if ($this->serviceEntity->chosenOffer->recordExists() && $this->serviceEntity->chosenOffer->paymentIdCreditCard) {
				$storage = new \App\Utils\CreditCard\Storage();
				$ccDet = $storage->getCard($this->serviceEntity->chosenOffer->paymentIdCreditCard);
				if ($ccDet) {
					$creditCardDetails = new \ModulesAbstract\PluginReports\ExtraSupport\ExtractCreditCardDetails\CreditCardDetails();
					$creditCardDetails->number = 			$ccDet['number'];
					$creditCardDetails->expireDate = 		$ccDet['expireDate'];
					$creditCardDetails->approvalCode = 		$this->serviceEntity->chosenOffer->paymentCcApprovalCode;
					$creditCardDetails->company =			$ccDet['company'];
					$creditCardDetails->ccDataSource = 		__FUNCTION__;
					return $creditCardDetails;
				}
			}
		}
		return null;
	}

	protected function extract_service_offer_formOfPayment_maskedNumber()
	{
		if ($this->serviceEntity->recordExists()) {
			if ($this->serviceEntity->chosenOffer->recordExists() && $this->serviceEntity->chosenOffer->paymentIdCreditCard) {
				$storage = new \App\Utils\CreditCard\Storage();
				$ccDet = $storage->getCard($this->serviceEntity->chosenOffer->paymentIdCreditCard);
				if ($ccDet) {
					$creditCardDetails = new \ModulesAbstract\PluginReports\ExtraSupport\ExtractCreditCardDetails\CreditCardDetails();
					$creditCardDetails->number = 			$ccDet['truncatedNumber'];
					$creditCardDetails->expireDate = 		$ccDet['expireDate'];
					$creditCardDetails->approvalCode = 		$this->serviceEntity->chosenOffer->paymentCcApprovalCode;
					$creditCardDetails->company =			$ccDet['company'];
					$creditCardDetails->ccDataSource = 		__FUNCTION__;
					return $creditCardDetails;
				}
			}
		}
		return null;
	}

	/**
	 * Extracts CC details from FOC with original number
	 * @return CreditCardDetails|NULL
	 */
	protected function extract_service_offer_formOfCashing_originalNumber()
	{
		if ($this->serviceEntity->recordExists()) {
			if ($this->serviceEntity->chosenOffer->recordExists() && $this->serviceEntity->chosenOffer->cashingIdCreditCard) {
				$storage = new \App\Utils\CreditCard\Storage();
				$ccDet = $storage->getCard($this->serviceEntity->chosenOffer->cashingIdCreditCard);
				if ($ccDet) {
					$creditCardDetails = new \ModulesAbstract\PluginReports\ExtraSupport\ExtractCreditCardDetails\CreditCardDetails();
					$creditCardDetails->number = 			$ccDet['number'];
					$creditCardDetails->expireDate = 		$ccDet['expireDate'];
					$creditCardDetails->approvalCode = 		$this->serviceEntity->chosenOffer->cashingCcApprovalCode;
					$creditCardDetails->company =			$ccDet['company'];
					$creditCardDetails->ccDataSource = 		__FUNCTION__;
					return $creditCardDetails;
				}
			}
		}

		return null;
	}

	/**
	 * Extracts CC details from FOC with masked number
	 * @return CreditCardDetails|NULL
	 */
	protected function extract_service_offer_formOfCashing_maskedNumber()
	{
		if ($this->serviceEntity->recordExists()) {
			if ($this->serviceEntity->chosenOffer->recordExists() && $this->serviceEntity->chosenOffer->cashingIdCreditCard) {
				$storage = new \App\Utils\CreditCard\Storage();
				$ccDet = $storage->getCard($this->serviceEntity->chosenOffer->cashingIdCreditCard);
				if ($ccDet) {
					$creditCardDetails = new \ModulesAbstract\PluginReports\ExtraSupport\ExtractCreditCardDetails\CreditCardDetails();
					$creditCardDetails->number = 			$ccDet['truncatedNumber'];
					$creditCardDetails->expireDate = 		$ccDet['expireDate'];
					$creditCardDetails->approvalCode = 		$this->serviceEntity->chosenOffer->cashingCcApprovalCode;
					$creditCardDetails->company =			$ccDet['company'];
					$creditCardDetails->ccDataSource = 		__FUNCTION__;
					return $creditCardDetails;
				}
			}
		}

		return null;
	}

	/**
	 * Extract CC details from Imported Order offer with original number
	 * @return CreditCardDetails|NULL
	 */
	protected function extract_importedService_offer_originalNumber()
	{
		if ($this->serviceEntity->importedService->recordExists()) {
			$importedServiceChosenOffer = $this->serviceEntity->importedService->object->chosenOffer;
			/* @var $importedServiceChosenOffer \App\ImportedOrder\Offer */
			if ($importedServiceChosenOffer) {
				$impCcObject = $importedServiceChosenOffer->creditCard;
				if ($impCcObject) {
					$creditCardDetails = new \ModulesAbstract\PluginReports\ExtraSupport\ExtractCreditCardDetails\CreditCardDetails();
					$creditCardDetails->number = 			$impCcObject->getOriginalNumber();
					$creditCardDetails->expireDate = 		$impCcObject->expireDate;
					$creditCardDetails->approvalCode = 		$impCcObject->approvalCode;
					$creditCardDetails->company =			$impCcObject->company;
					$creditCardDetails->ccDataSource = 		__FUNCTION__;
					return $creditCardDetails;
				}
			}
		}
		return null;
	}

	/**
	 * Extract CC details from Imported Order offer with masked number
	 * @return CreditCardDetails|NULL
	 */
	protected function extract_importedService_offer_maskedNumber()
	{
		if ($this->serviceEntity->importedService->recordExists()) {
			$importedServiceChosenOffer = $this->serviceEntity->importedService->object->chosenOffer;
			/* @var $importedServiceChosenOffer \App\ImportedOrder\Offer */
			if ($importedServiceChosenOffer) {
				$impCcObject = $importedServiceChosenOffer->creditCard;
				if ($impCcObject) {
					$creditCardDetails = new \ModulesAbstract\PluginReports\ExtraSupport\ExtractCreditCardDetails\CreditCardDetails();
					$creditCardDetails->number = 			$impCcObject->getMaskedNumber();
					$creditCardDetails->expireDate = 		$impCcObject->expireDate;
					$creditCardDetails->approvalCode = 		$impCcObject->approvalCode;
					$creditCardDetails->company =			$impCcObject->company;
					$creditCardDetails->ccDataSource = 		__FUNCTION__;
					return $creditCardDetails;
				}
			}
		}
		return null;
	}

	/**
	 * Extract CC details from relevant Imported Service offer with original number
	 * @return CreditCardDetails|NULL
	 */
	protected function extract_relevantImportedService_offer_originalNumber()
	{
		if ($this->serviceEntity->relevantImportedService->recordExists()) {
			$importedServiceChosenOffer = $this->serviceEntity->relevantImportedService->object->chosenOffer;
			/* @var $importedServiceChosenOffer \App\ImportedOrder\Offer */
			if ($importedServiceChosenOffer) {
				$impCcObject = $importedServiceChosenOffer->creditCard;
				if ($impCcObject) {
					$creditCardDetails = new \ModulesAbstract\PluginReports\ExtraSupport\ExtractCreditCardDetails\CreditCardDetails();
					$creditCardDetails->number = 			$impCcObject->getOriginalNumber();
					$creditCardDetails->expireDate = 		$impCcObject->expireDate;
					$creditCardDetails->approvalCode = 		$impCcObject->approvalCode;
					$creditCardDetails->company =			$impCcObject->company;
					$creditCardDetails->ccDataSource = 		__FUNCTION__;
					return $creditCardDetails;
				}
			}
		}
		return null;
	}

	/**
	 * Extract CC details from relevant Imported Service offer with masked number
	 * @return CreditCardDetails|NULL
	 */
	protected function extract_relevantImportedService_offer_maskedNumber()
	{
		if ($this->serviceEntity->relevantImportedService->recordExists()) {
			$importedServiceChosenOffer = $this->serviceEntity->relevantImportedService->object->chosenOffer;
			/* @var $importedServiceChosenOffer \App\ImportedOrder\Offer */
			if ($importedServiceChosenOffer) {
				$impCcObject = $importedServiceChosenOffer->creditCard;
				if ($impCcObject) {
					$creditCardDetails = new \ModulesAbstract\PluginReports\ExtraSupport\ExtractCreditCardDetails\CreditCardDetails();
					$creditCardDetails->number = 			$impCcObject->getMaskedNumber();
					$creditCardDetails->expireDate = 		$impCcObject->expireDate;
					$creditCardDetails->approvalCode = 		$impCcObject->approvalCode;
					$creditCardDetails->company =			$impCcObject->company;
					$creditCardDetails->ccDataSource = 		__FUNCTION__;
					return $creditCardDetails;
				}
			}
		}
		return null;
	}

	/**
	 * TODO this should be removed
	 * Extract CC details from corporate - CC associations
	 * @return CreditCardDetails|NULL
	 */
	protected function extract_from_plugin_ccAssociations()
	{
		if ($this->invoiceEntity && $this->ccAssoc) {
			if (array_key_exists($this->invoiceEntity->corporate->id, $this->ccAssoc)) {
				$creditCardDetails = new \ModulesAbstract\PluginReports\ExtraSupport\ExtractCreditCardDetails\CreditCardDetails();
				$creditCardDetails->number = 			$this->ccAssoc[$this->invoiceEntity->corporate->id]['ccNumber'];
				$creditCardDetails->expireDate = 		$this->ccAssoc[$this->invoiceEntity->corporate->id]['expiryDate'];
				$creditCardDetails->approvalCode = 		$this->ccAssoc[$this->invoiceEntity->corporate->id]['approvalCode'];
				$creditCardDetails->ccDataSource = 		__FUNCTION__;
				return $creditCardDetails;
			}
		}
		return null;
	}

}
