 #!/usr/bin/php
<?php
/*
 * 	Predicitve dialer by RMplus d.o.o. v2.0.0
 * 	Parameter for predictive dialer is ID of the project
 */	

	include_once("./predictive_config.php");

	require_once("./class.RM_AsteriskManager_predictive.php");
	//require_once("./predictive/class.AMI_PredictiveDialer.php");
	

    ini_set("max_execution_time", "0");
    ini_set("max_input_time", "0");
    set_time_limit(0);

	$asterisk_connect = explode(",", $telephone_asterisk_dialing);
	$asterisk_ip_port = $asterisk_connect[0];
	$asterisk_ip_port_array = explode(":",$asterisk_ip_port);
	$asterisk_ip = $asterisk_ip_port_array[0];
	$asterisk_port = $asterisk_ip_port_array[1];
  		
	$asterisk_username = $asterisk_connect[1]; 
	$asterisk_password = $asterisk_connect[2];
	$SIP = "700";
	$id_user = "-700";
	
	
	$am = new RM_AsteriskManager_predictive;
	
	if ($am->LogOn($asterisk_username, $asterisk_password, $asterisk_ip, $asterisk_port, $SIP, $id_user)) {
 		$am->AM_LogWrite_predictive("Predictive login successful!");
 		$am->AM_LogWrite_predictive("Asterisk AMI ok! Loging out from the socket, father does not need this connection: ".$am->mSocket);
 		$am->Logoff();
 		$am->AM_LogWrite_predictive("Did I loged out? Socket resurse=".$am->mSocket);
 		
 		$id_project = $argv[1];

 		
		$connect = $am->ConnectDB($host_to_connect, $host_username, $host_password);
		if (!$connect) {
			$am->AM_LogWrite_predictive("MySQL connect error!");
			$continueLoop = false;
			continue;
		}
		

		$am->AM_LogWrite_predictive("Empty asterisk_ringing table");
		$am->dbDeleteAllRingingCalls($id_project, $connect);
 		
 		$projectName = $am->dbGetProjectName($id_project, $connect);
		$am->AM_LogWrite_predictive("Get project name: ".$projectName);

 		//$am->EventsOn();
				
		$zombieTimeOut = 60;
		$nextTimeToClearZombies = time() + $zombieTimeOut;
		$timeToStopLoop = $zombieTimeOut;
		
		// time to stop id people forget to logout
		$date_and_time_to_stop = strtotime(date("Y-m-d")." ".$time_to_stop);		
						
		// initialize telephone number container;
		$am->TelNumberContainer = array();

		$continueLoop = true;
		// starting all the scripts
		while ($continueLoop) {	
				 		
			try  {
				if (!$connect) {
					$am->AM_LogWrite_predictive("MySQL connect does not exist, trying to establish the new one!");
					$connect = $am->ConnectDB($host_to_connect, $host_username, $host_password);
					if (!$connect) {
						$am->AM_LogWrite_predictive("MySQL connect error, inside loop!");
						$continueLoop = false;
						continue;
					}
				}
				
				// Getting the table parameters we will need later.
				$parameters = $am->dbGetProjectParameters($id_project, $connect);
				
				$timeout = $parameters['call_time_length']."000"; 
				$zombieTimeOut = (((int)$timeout)*2)/1000;
				
				// Should we continue looping?
				if ($parameters['predictive_work'] == 1) $doLoop = true; else $doLoop = false;
				
				if (!$doLoop) {
					// Demand for stoping the loop was issued.
					$am->AM_LogWrite_predictive("Predictive_work set to 0. Stopping the loop...");
					$am->AM_LogWrite_predictive("Waiting for children to finish their work...");
					$am->WaitForChildren();
					$am->AM_LogWrite_predictive("Predictive out!");
					
					$continueLoop = false;
					continue;
				}
				
				// is time over?
				$time_now = strtotime(date("Y-m-d H:i"));
				$am->AM_LogWrite_predictive("Time (".$time_now.") now...    AND time to stop".$date_and_time_to_stop);
				if ($time_now >= $date_and_time_to_stop) {
					$am->AM_LogWrite_predictive("Time (".$time_to_stop.") is up. Stopping the loop...");
					$am->WaitForChildren();
					$continueLoop = false;
					continue;
				}
								
				// How many calls are in process (ringing or before ringing)?
				$numberOfCallsInProcess = $am->dbGetNumOfRingingCalls($id_project, $connect);
				$am->AM_LogWrite_predictive("Number of already ringing calls: ".$numberOfCallsInProcess);
				
				// Getting the queue status.
				$AvailableQueueUsers = $am->CountQueueUsers($id_project, $connect);
				$am->AM_LogWrite_predictive("Users available in queue: ".$AvailableQueueUsers);
				
				if ($AvailableQueueUsers == 0) {
					$am->AM_LogWrite_predictive("No users in queue. Sleeping for 5 seconds");
					sleep (5);
					continue;
				}
				
				$numberOfExtraCalls = $am->dbGetNumofCallOverCalls($parameters,$AvailableQueueUsers);
				$numberOfExtraCalls += $AvailableQueueUsers;
				$numberOfExtraCalls -= $numberOfCallsInProcess;
				
				if ($numberOfExtraCalls < 0) $numberOfExtraCalls = 0;
				$am->AM_LogWrite_predictive("Available queue users: ".$AvailableQueueUsers.". Number of next calls: ".$numberOfExtraCalls);

				$am->dbGetTelephoneName($parameters, $connect);
				
				$am->AM_LogWrite_predictive("I am now inside loop ...! connect=$connect");
				//$connect = $am->Close($connect);
				//$am->AM_LogWrite_predictive("Closing MySQL connect in loop! connect=$connect");
				
				// we have to call some numbers
				if ($numberOfExtraCalls > 0) {
					for ($i = 0; $i < $numberOfExtraCalls; ++$i) {
						$am->AM_LogWrite_predictive("I am now inside for loop ...! i=$i and connect=$connect");
						
						if (!$connect) {
							$connect = $am->ConnectDB($host_to_connect, $host_username, $host_password);
							$am->AM_LogWrite_predictive("MySQL connect does not exist, trying to establish the new one! connect=$connect - Inside for loop ... searching new numbers.");
							if (!$connect) {
								$am->AM_LogWrite_predictive("MySQL connect error, inside for loop ...!");
								$i = $numberOfExtraCalls;
								$am->AM_LogWrite_predictive("Reset calls! Database error!");
								break;
							}
						}
								
						$isDogovor = false;
						try {
							$am->AM_LogWrite_predictive("Parameters for dbFindNumber:
														 project ID = $id_project, 
														 parameters = $parameters, 
														 project name = $projectName, 
														 id_user = $id_user, 
														 gsm array = $gsm_array, 
														 call regional = $call_regional, 
														 tel name = $am->tel_name, 
														 connect = $connect");
							$am->AM_LogWrite_predictive( json_encode($am->TelNumberContainer)  );
							if (count($am->TelNumberContainer) == 0) {
								$FindNumberStatus = $am->dbFindNumber($id_project, $parameters, $projectName, $id_user, $gsm_array, $call_regional, $am->tel_name, $izhodna_koda, $connect);
								
							} else {
								$FindNumberStatus = true;
							}
						} catch (Exception $e) {
							$sql = "UNLOCK TABLES";
							mysql_db_query($CATI_base_structure, $sql, $connect);
							$am->AM_LogWrite_predictive("ERROR: ".$e->getMessage());
							
							$FindNumberStatus = false;
						} 
						
						if ($FindNumberStatus == true) {
							$nextNumbertoCall = $am->getNewNumber($connect);
							$am->AM_LogWrite_predictive("I got number to call from getNewNumber(): ".$nextNumbertoCall);
						} else {
							$am->AM_LogWrite_predictive("Could not find number to call.");
							$sql = "UPDATE _Asterisk_RMconnect SET connect = 9 WHERE id_project = $id_project";
							mysql_db_query($CATI_base_structure,$sql,$connect);
							break;
						}
						
						$am->AM_LogWrite_predictive("Found a number from database.");
						$am->AM_LogWrite_predictive("Numbers id: ".$am->selectedIndex);
						$am->AM_LogWrite_predictive("Starting single call. Number: $nextNumbertoCall");

						$selectedTelephone = $am->selectedTelephone;
						$selectedNetwork = $am->selectedNetwork;
						$selectedRegion = $am->selectedRegion;
						$selectedIndex = $am->selectedIndex;
						$isAppointment = $am->isAppointment;
						$tel_name = $am->tel_name;

						
						$connect = $am->Close($connect);
						$am->AM_LogWrite_predictive("Closing MySQL connect in for loop...");
						
						// Making a child process
						$pid = pcntl_fork();
					 	if($pid == -1) 
					 		throw new Exception("Could not fork.");
					 	else if($pid == 0) {
					 		try  {
								$am_singlecall = new RM_AsteriskManager_predictive;
								$am_singlecall->AM_LogWrite_predictive("I am a child: ".getmypid());

								$am_singlecall->AM_LogWrite_predictive("Make child connection to MySQL");
								$connect = $am_singlecall->ConnectDB($host_to_connect, $host_username, $host_password);
								if (!$connect) {
									$am_singlecall->AM_LogWrite_predictive("MySQL connect error in child: ".getmypid());
									continue;
								}
								$am_singlecall->AM_LogWrite_predictive("Make child connection to MySQL. connect=$connect");
								
								if ($am_singlecall->LogOn($asterisk_username, $asterisk_password, $asterisk_ip, $asterisk_port, $SIP, $id_user)) {
									$am_singlecall->selectedTelephone = $selectedTelephone;
									$am_singlecall->selectedNetwork = $selectedNetwork ;
									$am_singlecall->selectedRegion = $selectedRegion;
									$am_singlecall->selectedIndex = $selectedIndex;
									$am_singlecall->isAppointment = $isAppointment;
									$am_singlecall->id_project = $id_project;
									$am_singlecall->tren_tabl = $projectName;
									$am_singlecall->tel_name = $tel_name;
									$am_singlecall->projectParameters = $parameters;
									
									$am_singlecall->asterisk_username = $asterisk_username; 
									$am_singlecall->asterisk_password = $asterisk_password;
									$am_singlecall->asterisk_ip = $asterisk_ip;
									$am_singlecall->asterisk_port = $asterisk_port; 
									$am_singlecall->SIP = $SIP;
									$am_singlecall->id_user = $id_user;
									
 									$am_singlecall->AM_LogWrite_predictive("Predictive login successful!");
								
									$am_singlecall->SetParameters($parameters);
									
									$am_singlecall->AM_LogWrite_predictive("Starting DialOutside.");
									$am_singlecall->DialOutside($nextNumbertoCall, $Context, $CallerID, $PredictiveExt, $TrunkName, $connect);
									//remove the call from ringing table
									$am_singlecall->dbDeleteRingingCall($id_project, $am_singlecall->DialOutside_actionID, $connect);
									
									$am_singlecall->AM_LogWrite_predictive("End DialOutside.");
									
							 		$am_singlecall->AM_LogWrite_predictive("Checking, if socket is alive (main child): ".$am_singlecall->mSocket);
									if ($am_singlecall->mSocket) {
										$am_singlecall->Logoff();
										$am_singlecall->AM_LogWrite_predictive("Socket Logoff()");
									}
							 		
									$am_singlecall->AM_LogWrite_predictive("Finishing child process: ".getmypid());
									exit();
									$am_singlecall->AM_LogWrite_predictive("WARNING: Still in child process: ".getmypid());
								}
								$connect = $am_singlecall->Close($connect);
								$am_singlecall->AM_LogWrite_predictive("Close child connection to MySQL. connect=$connect");
					 		}
					 		catch (Exception $e)
					 		{
					 			$am_singlecall->AM_LogWrite_predictive("WARNING. Exception in child ".getmypid()." ".$e->getMessage(), false);
					 			$am_singlecall->AM_LogWrite_predictive("Finishing child process: ".getmypid(), false);
								exit();
								$am_singlecall->AM_LogWrite_predictive("Still in child process: ".getmypid(), false);
					 		}
							$am->Close($connect);
							$am->AM_LogWrite_predictive("Closing MySQL connect in child.");
					 	} else {
							// This part is only executed in the parent
							$am->AM_LogWrite_predictive("Father: Sleeping for 1 second inside for loop ...");
	    					usleep(500000); 
						}
					}
				}
				
				// Wait for 2 sec.
				$am->AM_LogWrite_predictive("Father: Sleeping for 2 seconds inside loop ...");
				sleep(2);

				$am->ClearZombies($nextTimeToClearZombies, $zombieTimeOut);
			}
			catch (Exception $e)
			{
				$am->AM_LogWrite_predictive("ERROR: Catch father exception...");
				$exceptionMessage = $e->getMessage();
				$am->AM_LogWrite_predictive("Message: $exceptionMessage");
				throw $e;
			}
		}

	} else {
		$am->AM_LogWrite_predictive("EXCEPTION: ".$e->getMessage()."\n\r ");
		$am->AM_LogWrite_predictive("Waiting for children to finish their work...");
		$am->WaitForChildren();
	}

	
?>