<?php
/**
 * @package        RSForm! Pro
 * @copyright  (c) 2007 - 2016 RSJoomla!
 * @link           https://www.rsjoomla.com
 * @license        GNU General Public License http://www.gnu.org/licenses/gpl-3.0.en.html
 */

defined('_JEXEC') or die;

use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
use Joomla\CMS\Uri\Uri;
use Joomla\CMS\Form\Form;

define('RSFORM_FIELD_PAYMENT_PAYFAST', 512);

/**
 * Class plgSystemRsfppayfast
 */
class plgSystemRsfppayfast extends CMSPlugin
{
	/**
	 * @var bool
	 */
	protected $autoloadLanguage = true;
	/**
	 * @var int
	 */
	protected $componentId = RSFORM_FIELD_PAYMENT_PAYFAST;
	/**
	 * @var string
	 */
	protected $componentValue = 'payfast';

	protected $log = array();

	public function onRsformBackendAfterCreateFieldGroups(&$fieldGroups, $self)
	{
		$formId = Factory::getApplication()->input->getInt('formId');
		$exists = RSFormProHelper::componentExists($formId, RSFORM_FIELD_PAYMENT_PAYFAST);

		$fieldGroups['payment']->fields[] = (object) array(
			'id' 	=> RSFORM_FIELD_PAYMENT_PAYFAST,
			'name' 	=> Text::_('RSFP_PAYFAST_COMPONENT'),
			'icon'  => 'rsficon rsficon-coin-dollar',
			'exists' => $exists ? $exists[0] : false
		);
	}

	/**
	 * @param $items
	 * @param $formId
	 */
	public function onRsformGetPayment(&$items, $formId)
	{
		if ($components = RSFormProHelper::componentExists($formId, $this->componentId))
		{
			$data = RSFormProHelper::getComponentProperties($components[0]);

			$item        = new stdClass();
			$item->id    = $components[0];
			$item->value = $this->componentValue;
			$item->text  = $data['LABEL'];
			
			if ($tax = RSFormProHelper::getConfig('payfast.taxvalue'))
			{
				$item->tax = $tax;
				$item->tax_type = RSFormProHelper::getConfig('payfast.taxtype') == '0' ? 'percent' : 'fixed';

			}

			// add to array
			$items[] = $item;
		}
	}

	/**
	 * @throws Exception
	 */
	public function onRsformFrontendSwitchTasks()
	{
		$input  = Factory::getApplication()->input;
		$formId = $input->getInt('formId', 0);
		$task   = $input->getString('plugin_task', '');

		if ($task == 'payfast.notify')
		{
			$this->payFastITN();
		}

		if ($task == 'payfast.return')
		{
			$this->payFastReturn($formId);
		}
	}
	
	protected function payFastReturn($formId)
	{
		// Get session object
		$session = Factory::getSession();
		$app = Factory::getApplication();
		// Get data from session
		$formparams = $session->get('com_rsform.formparams.formId'.$formId);
		if ($formparams && $formparams->redirectUrl)
		{
			// Mark form as processed
			$formparams->formProcessed = true;

			// Store new session data
			$session->set('com_rsform.formparams.formId'.$formId, $formparams);

			// Redirect
			$app->redirect($formparams->redirectUrl);
		}
	}

	/**
	 * @param $formId
	 */
	protected function payFastITN()
	{
		header('HTTP/1.0 200 OK');
		flush();

		require_once JPATH_ADMINISTRATOR . '/components/com_rsform/helpers/PayFast/PayFast.php';

		$PayFast = RSFPPayFast::getInstance();

		try
        {
	        $PayFast->itn();
        }
		catch (Exception $e)
        {
            $this->addLogEntry(print_r($_POST, true));
            $this->addLogEntry($e->getMessage());
            $this->writeLog();
        }
	}

	/**
	 * Helper function to add messages to the log
	 *
	 * @param $message
	 */
	protected function addLogEntry($message)
	{
		$this->log[] = Factory::getDate()->toSql() . ' : ' . $message;
	}

	protected function writeLog()
	{
		// Need to separate IPN entries
		$this->addLogEntry("----------------------------- \n");

		$config   = Factory::getConfig();
		$log_path = $config->get('log_path') . '/rsformpro_payfast_log.php';
		$log      = implode("\n", $this->log);

		/**
		 * If it's the first time we write in it, we need to add die() at the beginning of the file
		 */
		if (is_writable($config->get('log_path')))
		{
			if (!file_exists($log_path))
			{
				file_put_contents($log_path, "<?php die(); ?>\n");
			}

			/**
			 * we start appending log entries
			 */
			file_put_contents($log_path, $log, FILE_APPEND);
		}
	}

	/**
	 * @param $payValue
	 * @param $formId
	 * @param $SubmissionId
	 * @param $price
	 * @param $products
	 * @param $code
	 *
	 * @throws Exception
	 */
	public function onRsformDoPayment($payValue, $formId, $SubmissionId, $price, $products, $code)
	{
		// execute only for our plugin
		if ($payValue != $this->componentValue)
		{
			return;
		}

		if ($price > 0)
		{
			try
			{
				/**
				 * Get the calculated price (with tax)
				 */
				if ($tax = RSFormProHelper::getConfig('payfast.taxvalue'))
				{
					$price = $this->calcTax($price, RSFormProHelper::getConfig('payfast.taxvalue'), RSFormProHelper::getConfig('payfast.taxtype'));
				}

				/**
				 * Build the description based on products.
				 * In case it's an array, we convert it as string
				 */
				$description = $products;
				if (is_array($description))
				{
					$description = substr(implode(', ', $products), 0, 100);
				}

				$vars = array(
					'return_url'   => Route::_(Uri::root() . 'index.php?option=com_rsform&formId=' . $formId . '&task=plugin&plugin_task=payfast.return&SubmissionId=' . $SubmissionId),
					'notify_url'   => Route::_(Uri::root() . 'index.php?option=com_rsform&formId=' . $formId . '&task=plugin&plugin_task=payfast.notify&code=' . $code),
					'amount'       => number_format(sprintf('%.2f', $price), 2, '.', ''),
					'item_name'    => $description,
				);

				require_once JPATH_ADMINISTRATOR . '/components/com_rsform/helpers/PayFast/PayFast.php';
				$PayFast = RSFPPayFast::getInstance();
				
				// If any options have already been set, use this to override the ones used here
                foreach ($vars as $var => $value)
                {
                    if (empty($PayFast->args[$var]))
                    {
                        $PayFast->args[$var] = $value;
                    }
                }

				$PayFast->code = $code;
				$PayFast->submissionId = $SubmissionId;
				
				$PayFast->redirect();
			}
			catch (Exception $e)
			{
				Factory::getApplication()->enqueueMessage($e->getMessage(), 'warning');
			}

		}
	}

	/**
	 * Add a grand total and tax placeholder
	 *
	 * @param $args
	 */
	public function onRsformAfterCreatePlaceholders($args)
	{
		if ($choosePayment = RSFormProHelper::componentExists($args['form']->FormId, RSFORM_FIELD_PAYMENT_CHOOSE))
		{
			$properties = RSFormProHelper::getComponentProperties($choosePayment[0]);
			$fieldName = $properties['NAME'];

			if (!isset($args['submission']->values[$fieldName]))
			{
				return;
			}

			if ($args['submission']->values[$fieldName] != $this->componentValue)
			{
				return;
			}

			$grandTotal = $this->calcTax($args['submission']->values['rsfp_Total'], RSFormProHelper::getConfig('payfast.taxvalue'), RSFormProHelper::getConfig('payfast.taxtype'));

			$placeholders = &$args['placeholders'];
			$values       = &$args['values'];

			$placeholders[] = '{grandtotal}';
			$values[]       = $this->number_format($grandTotal);

			$placeholders[] = '{tax}';
			$values[]       = $this->number_format($grandTotal - (float) $args['submission']->values['rsfp_Total']);
		}
	}

	private function number_format($val)
	{
		return number_format((float) $val, RSFormProHelper::getConfig('payment.nodecimals'), RSFormProHelper::getConfig('payment.decimal'), RSFormProHelper::getConfig('payment.thousands'));
	}

	/**
	 * @param array $args
	 */
	public function onRsformBackendAfterCreateComponentPreview($args = array())
	{
		if ($args['ComponentTypeName'] == $this->componentValue)
		{
			$args['out'] = '<span style="font-size:24px;margin-right:5px" class="rsficon rsficon-coin-dollar"></span> ' . $args['data']['LABEL'];
		}
	}

	/**
	 * @param $placeholders
	 * @param $componentId
	 *
	 * @return mixed
	 * @since 1.0.3
	 */
	public function onRsformAfterCreateQuickAddPlaceholders(& $placeholders, $componentId)
	{
		if ($componentId == $this->componentId)
		{
			$placeholders['display'][] = '{grandtotal}';
			$placeholders['display'][] = '{tax}';
		}

		return $placeholders;
	}

	public function onRsformDefineHiddenComponents(&$hiddenComponents)
	{
		$hiddenComponents[] = $this->componentId;
	}

	/**
	 * @param $tabs
	 */
	public function onRsformBackendAfterShowConfigurationTabs($tabs)
	{
		$tabs->addTitle(Text::_('RSFP_PAYFAST_LABEL'), 'page-payfast');
		$tabs->addContent($this->showConfigurationScreen());
	}

	private function loadFormData()
	{
		$data 	= array();
		$db 	= Factory::getDbo();

		$query = $db->getQuery(true)
			->select('*')
			->from($db->qn('#__rsform_config'))
			->where($db->qn('SettingName') . ' LIKE ' . $db->q('payfast.%', false));
		if ($results = $db->setQuery($query)->loadObjectList())
		{
			foreach ($results as $result)
			{
				$data[$result->SettingName] = $result->SettingValue;
			}
		}

		return $data;
	}

	protected function showConfigurationScreen()
	{
		ob_start();

		Form::addFormPath(__DIR__ . '/forms');

		$form = Form::getInstance( 'plg_system_rsfppayfast.configuration', 'configuration', array('control' => 'rsformConfig'), false, false );
		$form->bind($this->loadFormData());

		?>
        <div id="page-payfast" class="form-horizontal">
			<?php
			foreach ($form->getFieldsets() as $fieldset)
			{
				if ($fields = $form->getFieldset($fieldset->name))
				{
					foreach ($fields as $field)
					{
						// This is a workaround because our fields are named "payfast." and Joomla! uses the dot as a separator and transforms the JSON into [payfast][apikey] instead of [payfast.apikey].
						echo str_replace('"rsformConfig[payfast][', '"rsformConfig[payfast.', $form->renderField($field->fieldname));
					}
				}
			}
			?>
        </div>
		<?php

		$contents = ob_get_contents();
		ob_end_clean();

		return $contents;
	}


	/**
	 * @param $price
	 * @param $amount
	 * @param $type
	 *
	 * @return mixed
	 */
	public function calcTax($price, $amount, $type)
	{
		$price = (float) $price;
		$amount = (float) $amount;

		switch ($type)
		{
			case false:
				$price = $price + (($price * $amount) / 100);
				break;

			case true:
				$price = $price + $amount;
				break;
		}

		return $price;
	}
}