<?php defined('SYSPATH') or die('No direct access allowed.');

/**
 * This class supports Tasks
 *
 * @package    OSB
 * @subpackage Task
 * @category   Models
 * @author     Deon George
 * @copyright  (c) 2010 Open Source Billing
 * @license    http://dev.osbill.net/license.html
 */
class Model_Task extends ORM_OSB {
	protected $_display_filters = array(
		'date_run'=>array(
			array('Config::datetime',array(':value')),
		),
	);

	public function run($force=FALSE) {
		$r = rand(0,9999);
		$tlo = ORM::factory('Task_Log');
		$tlo->task_id = $this->id;

		if (! $this->loaded())
			$tlo->message = sprintf('Unknown Task ID %s',$this->id);

		elseif (! $this->status)
			$tlo->message = sprintf('Task %s is not active',$this->id);

		elseif ($this->running AND ! $force)
			$tlo->message = sprintf('Task %s is already running',$this->id);

		elseif (! preg_match('/\//',$this->command))
			$tlo->message = sprintf('Task %s uses the old configuration, ignoring :command',$this->id,$this->command);

		else {
			try {
				// Get a lock
				$this->running = 1;
				$this->running_host = $r;
				$this->save();

				// Check we are the winning host to run this task
				// @todo We need to test that the lock is not stale
				$this->reload();
				if ($this->running_host != $r)
					return;

				switch ($this->type) {
					case 0:
						$r = Request::factory($this->command)->execute();
						break;

					default:
						throw new Kohana_Exception('Unknown task type :type',array(':type'=>$this->type));
				}

				// Clear our lock and update the last run time
				$this->date_run = time();
				$this->running = 0;
				$this->running_host = NULL;

				$tlo->result = 0;
				$tlo->message = $r->body();
			}
			catch (Exception $e) {
				$tlo->result = $e->getCode();
				$tlo->message = Kohana_Exception::text($e);

				$this->running = 1;
				$this->running_host = 'ERROR';
			}

			$this->save();
		}

		if ($this->log)
			$tlo->save();
	}

	/** LIST FUNCTIONS **/

	public function list_active() {
		$return = array();

		foreach ($this->_where_active()->find_all() as $to) {
			$ct = sprintf('%s %s %s %s %s',$to->int_min,$to->int_hour,$to->int_month_day,$to->int_month,$to->int_week_day);

			$c = new Cron($ct,$to->command);
			$return[$to->id]['task'] = $to;
			$return[$to->id]['next'] = $c->next($to->date_run);
		}

		return $return;
	}

	public function list_next() {
		$return = array();

		foreach ($this->list_active() as $v)
			if ((! $return OR $v['next']<$return['next']) AND ! $v['task']->running)
				$return = $v;

		return array($return['task']->id=>$return);
	}
}
?>