<?php
/**
 * @package     jAtomS Package
 * @subpackage  com_jatoms
 * @version     __DEPLOY_VERSION__
 * @author      Atom-S - atom-s.com
 * @copyright   Copyright (c) 2017 - 2021 Atom-S LLC. All rights reserved.
 * @license     GNU/GPL license: https://www.gnu.org/copyleft/gpl.html
 * @link        https://atom-s.com/
 */

defined('_JEXEC') or die;

use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Log\Log;
use Joomla\CMS\MVC\Controller\BaseController;
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
use Joomla\CMS\Response\JsonResponse;
use Joomla\Input\Json;
use Joomla\Registry\Registry;

class jAtomSControllerConnect extends BaseController
{
	/**
	 * Controller context string.
	 *
	 * @var  string
	 *
	 * @since  2.2.0
	 */
	protected $_context = 'com_jatoms.connect';

	/**
	 * Controller access string.
	 *
	 * @var  boolean
	 *
	 * @since  2.2.0
	 */
	protected $_access = null;

	/**
	 * Component params.
	 *
	 * @var  Registry
	 *
	 * @since  2.2.0
	 */
	protected $params = null;

	/**
	 * Response code.
	 *
	 * @var  integer
	 *
	 * @since  2.2.0
	 */
	protected $code = null;

	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @throws Exception
	 *
	 * @since  2.2.0
	 */
	public function __construct($config = array())
	{
		// Add json input
		$app = Factory::getApplication();
		if ($data = new Json())
		{
			foreach ($data->getArray() as $name => $value)
			{
				$app->input->def($name, $value);
			}
		}

		// Parent constructor
		$config['default_task'] = false;
		$config['default_view'] = false;

		$result = parent::__construct($config);
		if (($key = array_search('display', $this->methods)) !== false)
		{
			unset($this->methods[$key]);
		}
		unset($this->taskMap['display']);

		// Add logger
		Log::addLogger(array(
			'text_file'         => 'com_jatoms_connect.php',
			'text_entry_format' => "{DATETIME}\t{CLIENTIP}\t{MESSAGE}\t{PRIORITY}"),
			Log::ALL, array('com_jatoms_connect'));

		// Set params
		$this->params = ComponentHelper::getParams('com_jatoms');

		// Check access
		$this->checkAccess();

		return $result;
	}

	/**
	 * Change order state hook.
	 *
	 * @throws  Exception
	 *
	 * @return  array Response data array.
	 *
	 * @since  2.2.0
	 */
	public function onOrderCreated()
	{
		// Check access
		$event    = $this->input->getCmd('event_name', '');
		$response = array('event' => $event);

		// Check event
		if ($event !== 'order_created') throw new Exception(Text::_('COM_JATOMS_ERROR_CONNECT_EVENT_NOT_SUPPORT'), 500);

		$oder_id              = $this->input->getInt('order', 0);
		$response['order_id'] = $oder_id;

		// @var jAtomSModelConnect $model
		$model = $this->getModel();
		$model->setState('params', $this->params);

		// Get order
		if (!$order = $model->getOrder($oder_id))
		{
			$messages = array();
			foreach ($model->getErrors() as $error)
			{
				$messages[] = ($error instanceof Exception) ? $error->getMessage() : $error;
			}

			throw new Exception(implode(PHP_EOL, $messages), 404);
		}
		$response['tour_id'] = $order->order->tour_id;

		// Get tour
		if (!$tour = $model->getTour($order->order->tour_id))
		{
			$messages = array();
			foreach ($model->getErrors() as $error)
			{
				$messages[] = ($error instanceof Exception) ? $error->getMessage() : $error;
			}

			throw new Exception(implode(PHP_EOL, $messages), 404);
		}

		// Process the jatoms plugins
		if ($plugins = $model->triggerPlugins('onjAtomSOrderCreated', array($order, $tour, $this->params)))
		{
			foreach ($plugins as $p => $plugin)
			{
				// Add to response
				$response[$p] = $plugin['result'];

				// Add logs
				Log::add($plugin['title'] . ': ' . $plugin['result'],
					($plugin['error']) ? Log::ERROR : Log::INFO, 'com_jatoms_connect');
			}
		}

		$this->message = Text::sprintf('COM_JATOMS_CONNECT_MESSAGES_ORDER_CREATED', $oder_id);

		return $response;
	}

	/**
	 * Method to check access key.
	 *
	 * @throws Exception
	 *
	 * @return  boolean True on success, false on failure.
	 *
	 * @since  2.2.0
	 */
	protected function checkAccess()
	{
		if ($this->_access === null)
		{
			$token         = $this->input->get('token');
			$params        = $this->params->get('connect_token');
			$this->_access = (!empty($token) && !empty($params) && $token === $params);
		}

		if (!$this->_access)
		{
			$this->code    = 401;
			$this->message = Text::_('COM_JATOMS_ERROR_CONNECT_INVALID_TOKEN');
			$this->setResponse();
		}

		return $this->_access;
	}

	/**
	 * Execute a task by triggering a method in the derived class.
	 *
	 * @param   string  $task  The task to perform.
	 *
	 * @throws  Exception
	 *
	 * @return  boolean   True on success, False on failure.
	 *
	 * @since   2.2.0
	 */
	public function execute($task)
	{
		try
		{
			$response = parent::execute($task);
		}
		catch (Exception $e)
		{
			$response      = null;
			$this->message = $e->getMessage();
			$this->code    = $e->getCode();
		}

		return $this->setResponse($response);
	}

	/**
	 * Method to set json response.
	 *
	 * @param   mixed  $response  Response data.
	 *
	 * @throws  Exception
	 *
	 * @return  boolean True on success, false on failure.
	 *
	 * @since  2.2.0
	 */
	protected function setResponse($response = null)
	{
		$message = (is_array($this->message)) ? implode(PHP_EOL, $this->message) : $this->message;
		$code    = (!empty($this->code)) ? $this->code : 200;

		// Add logs
		Log::add($message, ($code !== 200) ? Log::ERROR : Log::INFO, 'com_jatoms_connect');

		header('Content-Type: application/json');
		echo new JsonResponse($response, $message, ($code !== 200));
		Factory::getApplication()->close($code);

		return ($code === 200);
	}

	/**
	 * Proxy for getModel.
	 *
	 * @param   string  $name    The model name.
	 * @param   string  $prefix  The class prefix.
	 * @param   array   $config  The array of possible config values.
	 *
	 * @return  BaseDatabaseModel|jAtomSModelConnect  A model object.
	 *
	 * @since  2.2.0
	 */
	public function getModel($name = 'Connect', $prefix = 'jAtomSModel', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, $config);
	}
}