<?php
/**
 * @package     Reporter for VirtueMart
 * 
 * @copyright   Copyright (C) 2012-2021 VirtuePlanet Services LLP. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 * @author      Abhishek Das <info@virtueplanet.com> - https://www.virtueplanet.com
 */

defined('_JEXEC') or die;

use Joomla\Registry\Registry;

// Register shutdownScheduler
JLoader::register('VMReporterShutdownScheduler', JPATH_COMPONENT . '/helpers/shutdownscheduler.php');

/**
 * VMReporter Cronjob model.
 */
class VMReporterModelCronjob extends JModelLegacy
{
	/**
	 * @var   string  The prefix to use with controller messages.
	 */
	protected $text_prefix = 'COM_VMREPORTER';

	/**
	 * Returns a reference to the a Table object, always creating it.
	 *
	 * @param  type    The table type to instantiate
	 * @param  string  A prefix for the table class name. Optional.
	 * @param  array   Configuration array for model. Optional.
	 * 
	 * @return  JTable A database object
	 */
	public function getTable($type = 'Cron', $prefix = 'VMReporterTable', $config = array())
	{
		JTable::addIncludePath(JPATH_COMPONENT_ADMINISTRATOR . '/tables');
		
		return JTable::getInstance($type, $prefix, $config);
	}
	
	/**
	* 
	 * @param  type    The model type to instantiate
	 * @param  string  A prefix for the model class name. Optional.
	 * @param  array   Configuration array for model. Optional.
	* 
	* @return  JModelLegacy  A model object
	*/
	protected function getModel($type = 'Report', $prefix = 'VMReporterModel', $config = array('ignore_request' => true))
	{
		JModelLegacy::addIncludePath(JPATH_COMPONENT_ADMINISTRATOR . '/models');
		
		return JModelLegacy::getInstance($type, $prefix, $config);
	}
	
	/**
	* Run cron job
	* 
	* @return boolean
	*/
	public function run()
	{
		$db    = $this->getDbo();
		$date  = JFactory::getDate();
		$query = $db->getQuery(true);
		
		$query->select('c.' . $db->quoteName('id'))
		      ->from($db->quoteName('#__vmreporter_crons') . ' AS c')
		      ->join('INNER', $db->quoteName('#__vmreporter_templates') . ' AS t ON t.' . $db->quoteName('id') . ' = c.' . $db->quoteName('template_id'))
		      ->where('c.' . $db->quoteName('state') . ' = 1')
		      ->where('c.' . $db->quoteName('next_run_time') . ' <= ' . $db->quote($date->toSql()))
		      ->where('c.' . $db->quoteName('currently_running') . ' = 0');
		
		$db->setQuery($query);
		$pks = $db->loadColumn();

		// If no crons found
		if(empty($pks))
		{
			return true;
		}
		
		$table = $this->getTable();
		$model = $this->getModel('Report');
		$shutdownScheduler = new VMReporterShutdownScheduler();
		
		foreach($pks as $key => $pk)
		{
			// Load the selected cron
			if($table->load($pk))
			{
				// Set the cron is running to avoid multiple calling
				$table->setRunning($pk);
				
				$registry   = new Registry($table->log);
				$table->log = $registry->toArray();
				
				$newLog = new stdClass;
				$newLog->time = $date->toSql();
				$newLog->success = true;
				$newLog->message = JText::_('COM_VMREPORTER_NEW_REPORT_GENERATED');
				
				// Build an unique event name
				$eventName = 'clearRunning-' . $key;
				
				// Registered the shutdown function incase execution times out
				$shutdownScheduler->registerShutdownEvent($eventName, array($table, 'clearRunning'), $pk);
				
				// Generate the report for the cron
				$result = $model->generate($table->template_id, $table->send_mail, $table->email_ids);
				
				// Unregister shutdown function
				$shutdownScheduler->unregisterShutdownEvent($eventName);
				
				// In case of failure
				if($result === false)
				{
					$newLog->success = false;
					$newLog->message = $model->getError();
				}
				
				// In case any error message is set by mailer 
				elseif($error = $model->getError())
				{
					$newLog->message .= ' ' . $error; 
				}
				
				// Add new log
				$table->log[] = $newLog;
				
				// Increase hits count
				$table->hits++;
				
				// Run only once
				if($table->once_only)
				{
					// Unpublish the cron
					$table->state = 0;
				}
				
				// Set last run time
				if($table->next_run_time > 0 && $table->start_time > 0 && $table->start_time != $table->created_on)
				{
					$last_run_time = JFactory::getDate($table->next_run_time);
					
					$table->last_run_time = $last_run_time->toSql();
				}
				else
				{
					$table->last_run_time = $date->toSql();
				}
				
				// Cron stopped running
				$table->currently_running = 0;
				
				// Store cron
				$table->store();
			}
			
			// Reset cron table
			$table->reset();
		}
		
		return true;
	}
}