<?php
	require_once( $GLOBALS["site_root"] . "/includes/models/CronSynchronizer.inc.php" );
	require_once( $GLOBALS["site_root"] . "/includes/models/TaskManager.inc.php" );
	require_once( $GLOBALS["site_root"] . "/includes/models/Globals.inc.php" );

	class TaskProcessor {
		protected $bailout = false;
		protected $oCron;
		public $oTM;
		protected $sMutexFile = "/tmp/fordit_task.mutex";
		protected $hMutexFile = null;
		protected $aMiniTasks = array();

		public function log( $s = "" ) {
			$file = fopen( "/tmp/fordit_tasks.log" , "a" );
			if (!$file) return false;
			fputs( $file , sprintf( "%s: %s\n",
				fo3_date( "Y-m-d H:i:s" ),
				$s ) );
			fclose( $file );
			return true;
		}

		public function __construct() {

		}

		public function addMiniTask( $minitask ) {
			$this->aMiniTasks[]=$minitask;
		}

		protected function restartZombieTasks( ) {
			// 5 percnel oregebb taskok inactive-ra
			$query = sprintf( "update tasks set task_status='inactive' where task_status='active' and now()-task_mtstamp>'00:05:00'" );
			FNTH_db_free_result( FNTH_db_query( $query ) );
		}

		protected function processMiniTasks() {
			foreach ($this->aMiniTasks as $minitask) {
				require_once( $GLOBALS["site_root"]."/includes/tasks/".$minitask.".inc.php" );
				$mt = new $minitask( 0 , $this );
				$mt->processTask();
			}
		}

		protected function waitForMutex( $time = 0 ) {
			$this->hMutexFile = fopen( $this->sMutexFile , "w" );
			if (!$this->hMutexFile) return false;
			$lock = flock( $this->hMutexFile , LOCK_EX | LOCK_NB );
			while (!$lock) {
				if (!$time) {
					fclose( $this->hMutexFile );
					return false;
				}
				$time--;
				$lock = flock( $this->hMutexFile , LOCK_EX | LOCK_NB );
			}
			return true;
		}

		protected function releaseMutex() {
			if (!$this->hMutexFile) return false;
			fclose( $this->hMutexFile );
			if (file_exists( "/tmp/fordit.stop" )) unlink( "/tmp/fordit.stop" );
			return true;
		}

		protected function processTask( $task_id ) {
			if (!$this->oTM->acquireTask( $task_id )) {
				$this->bailout = true;
				return false;
			}
			switch ($this->oTM->getTaskType()) {
			case "shuffle_members":
				require_once( $GLOBALS["site_root"]."/includes/tasks/ShuffleTask.inc.php" );
				$st = new ShuffleTask( $task_id , $this );
				$st->processTask();
				break;
			case "job_activation":
			case "job_notification":
				require_once( $GLOBALS["site_root"]."/includes/tasks/JobTask.inc.php" );
				$jt = new JobTask( $task_id , $this );
				$jt->processTask();
				break;
			case "status_regen":
				require_once( $GLOBALS["site_root"]."/includes/tasks/StatusRegenTask.inc.php" );
				$srt = new StatusRegenTask( $task_id , $this );
				$srt->processTask();
				break;
			case "status_send":
				require_once( $GLOBALS["site_root"]."/includes/tasks/StatusSendTask.inc.php" );
				$srt = new StatusSendTask( $task_id , $this );
				$srt->processTask();
				break;
			case "newsletter_activation":
			case "newsletter_send":
				require_once( $GLOBALS["site_root"]."/includes/tasks/NewsletterTask.inc.php" );
				$nt = new NewsletterTask( $task_id , $this );
				$nt->processTask();
				break;
			case "finish_unfinisheds":
				require_once( $GLOBALS["site_root"]."/includes/tasks/FinishUnfinishedTransactionsTask.inc.php" );
				$futt = new FinishUnfinishedTransactionsTask( $task_id , $this );
				$futt->processTask();
				break;
			default:
				$this->oTM->closeTask( TASK_STATUS_UNKNOWN );
			}
		}

		public function timeLeft() {
			if (file_exists( "/tmp/fordit.stop" )) return 0;
			$timeleft = $this->oCron->timeLeft();
			$this->log( sprintf( "script: %3d ; cron: %3d ; overall: %3d",$timeleft["script_time"],$timeleft["cron_time"],$timeleft["overall_time"] ) );
			return $timeleft["overall_time"];
		}

		public function processTasks( $getparams ) {
			$use_cron = (isset( $getparams["cron"] ));
			$number_of_tasks = (isset( $getparams["number_of_tasks"] )) ? $getparams["number_of_tasks"] : 100;
			$onetask = (isset( $getparams["onetask"] ));

			$this->oCron = new CronSynchronizerModel( $use_cron );
			if (!$this->waitForMutex()) {
				$this->log( "task processor currently running, stopping 2nd instance" );
				return;
			}
			$this->oTM = new TaskManagerModel();
			$this->log( "task processor started" );
			$this->restartZombieTasks();
			$this->bailout=false;
			while ($this->timeLeft()>2) {
				$this->processMiniTasks();
				$task_ids = $this->oTM->getPendingInactiveTaskIds();
				while ($number_of_tasks && !$this->bailout) {
					if (count( $task_ids )) {
						$task_id = array_shift( $task_ids );
						$this->processTask( $task_id );
						$number_of_tasks--;
					} else {
						if ($onetask) break;
						sleep( 1 );
						break;
					}
				}
				if ($onetask) break;
			}
			$this->log( "task processor finished" );
			$this->releaseMutex();
		}
	}

?>
