<?php
use PhpAmqpLib\Connection\AMQPConnection;
use PhpAmqpLib\Message\AMQPMessage;
require_once _DIR_TO_ROOT.'/vendor/autoload.php';
// wget --no-check-certificate https://10.133.16.160/services/rabbit/listen_1c/
// 
class SimpleReceiver
{
    /**
     * Слушатели входящих сообщений
     */

    var $result ;
    var $log_results=0 ;
    var $write_log=1 ;

    function connection($vhost)
    {

        $connection = new AMQPConnection(
		    $GLOBALS['_SETTING']['rabbit']['host'],	#host
		    $GLOBALS['_SETTING']['rabbit']['port'],       	#port
		    $GLOBALS['_SETTING']['rabbit']['login'],    	#user
		    $GLOBALS['_SETTING']['rabbit']['password'],    	#password
		    $vhost
           );

	    return($connection) ;
    }


    public function listen($vhost,$routing)
    {   $connection=$this->connection($vhost) ;
        $channel = $connection->channel();

        /*$channel->queue_declare(
            $routing,	#имя очереди, такое же, как и у отправителя
            false,      	#пассивный
            false,      	#надёжный
            false,      	#эксклюзивный
            false       	#автоудаление
            );
          */
        $channel->basic_consume(
		    $routing,                	#очередь
            '',                         	#тег получателя - Идентификатор получателя, валидный в пределах текущего канала. Просто строка
            false,                      	#не локальный - TRUE: сервер не будет отправлять сообщения соединениям, которые сам опубликовал
            true,                       	#без подтверждения - отправлять соответствующее подтверждение обработчику, как только задача будет выполнена
            false,                      	#эксклюзивная - к очереди можно получить доступ только в рамках текущего соединения
            false,                      	#не ждать - TRUE: сервер не будет отвечать методу. Клиент не должен ждать ответа
            array($this, 'processOrder')	#функция обратного вызова - метод, который будет принимать сообщение
            );

	    if ($this->write_log) LOGS()->reg_log('rabbit','Выполнено подключение к каналу "<strong>'.$vhost.'/'.$routing.'</strong>" ') ;

        while(count($channel->callbacks))
        { try
          {
            $channel->wait();
          }
          catch(Exception $e)
          {  $this->result['error']=$e->getMessage() ;
             break ;
          }
        }

        $channel->close();
        $connection->close();
    }

    public function read($vhost,$routing,$exchange='')
    {   $connection=$this->connection($vhost) ;
        $channel = $connection->channel();
	    $this->result=array() ;
        $channel->basic_consume(
		    $routing,                	    #очередь
		    $exchange,                      #тег получателя - Идентификатор получателя, валидный в пределах текущего канала. Просто строка
            false,                      	#не локальный - TRUE: сервер не будет отправлять сообщения соединениям, которые сам опубликовал
            true,                       	#без подтверждения - отправлять соответствующее подтверждение обработчику, как только задача будет выполнена
            false,                      	#эксклюзивная - к очереди можно получить доступ только в рамках текущего соединения
            false,                      	#не ждать - TRUE: сервер не будет отвечать методу. Клиент не должен ждать ответа
            array($this, 'processOrder')	#функция обратного вызова - метод, который будет принимать сообщение
            );

	    //if ($this->write_log)  LOGS()->reg_log('rabbit','read on "<strong>'.$vhost.'/'.$routing.'</strong>" ') ;

	    $this->log_results=1 ;
	    while(count($channel->callbacks)) // пока есть сообщения
        { try
          {
          	$channel->wait(null,false,1);  // ждем новое сообщение 1 секунду
          }
          catch(Exception $e)
          {  $this->result['error']=$e->getMessage() ;
          	 break ;
          }
        }

        $channel->close();
        $connection->close();
        return($this->result) ;
    }

    /**
     * @param $msg
     */
    public function processOrder($msg)
    {   ob_start() ;
    	$data=json_decode($msg->body,1) ;
	    $props=$msg->get_properties() ;
	    $type=($props['type'])? $props['type']:'undefined' ;
	    $result=ENGINE()->on_event('rabbit_packet_received',array('props'=>$props,'mess'=>$data)) ;
	    if (!$result['no_show_result_data'])
	    { //echo $result['debug'] ;
	      damp_array($result,1,-1) ;
	    }
	    if ($this->log_results) $this->result['mess'][]='Получено сообщение с темой <strong>"'.$type.'"</strong>' ;

	    // 1 - входящее соощение
	    // 1 - сообщение обработано, 2 - неизвестная тема пакета, 3 - тема не определена
	    $text=ob_get_clean() ;
	    $this->log($msg,$props,$data,1,1,$text) ;
	    echo $text;
    }
    
	public function execute3($exchange,$routing,$props,$data)
	{   if (is_string($props)) $props=array('type'=>$props) ;
		$this->execute2($GLOBALS['_SETTING']['rabbit']['vhost'],$exchange,$routing,$props,$data) ;
	}

	public function execute2($vhost,$exchange,$routing,$props,$data,$options=array())
   {  if (is_string($props)) $props=array('type'=>$props) ;
   	  echo 'Отправляем пакет в обмен <strong>"'.$exchange.'/'.$routing.'"</strong> типа пакета <strong>'.$props['type'].'</strong>:' ;

	   $connection=$this->connection($vhost) ;
       $channel = $connection->channel();

       /*$channel->queue_declare(
		   $routing,	#queue name - Имя очереди может содержать до 255 байт UTF-8 символов
           false,      	#passive - может использоваться для проверки того, инициирован ли обмен, без того, чтобы изменять состояние сервера
           false,      	#durable - убедимся, что RabbitMQ никогда не потеряет очередь при падении - очередь переживёт перезагрузку брокера
           false,      	#exclusive - используется только одним соединением, и очередь будет удалена при закрытии соединения
           false       	#autodelete - очередь удаляется, когда отписывается последний подписчик
           );
       */
       //print_r($channel) ;
	   if (!$props['message_id']) $props['message_id']=ENGINE()->generate_UID() ;
	   $props['content_type']='application/json' ;
	   $props['content_encoding']='utf-8' ;

	   //damp_array($props,1,-1) ;


	   //damp_array($message) ;
	   $message=json_encode($data,JSON_UNESCAPED_UNICODE) ;
       $msg = new AMQPMessage($message,$props);

       $channel->basic_publish(
           $msg,       	#message
           $exchange,   #exchange
		   $routing 	#routing key
           );

       $channel->close();
       $connection->close();

	   // 2 - исходящее соощение
       // 1 - сообщение обработано,
       $this->log('',$props,$data,2,1,'',$options) ;
	   

       echo '<div class="green">Сообщение отправлено</div>'  ;
	   damp_array($data,1,-1) ;
   }

   function log($msg,$props,$data,$direct,$status,$comment='',$options=array())
   { $uid=ENGINE()->generate_UID() ;
	 //$uid=$data->message_id ;
	 if (is_object($data) and isset($data->message_id)) $uid=$data->message_id ;
	 if (is_array($data) and isset($data['message_id'])) $uid=$data['message_id'] ;
	 if (is_object($props) and isset($props->message_id)) $uid=$props->message_id ;
	 if (is_array($props) and isset($props['message_id'])) $uid=$props['message_id'] ;

	 if ($msg!=null)
	 {	ob_start() ; var_dump($msg) ;$msg_text=ob_get_clean() ;
	    $temp_fname_msg=_TEMP_DIR.'/rabbit_packet_'.$uid.'_msg.json' ;
        file_put_contents($temp_fname_msg,$msg_text) ;
        $temp_fname_body=_TEMP_DIR.'/rabbit_packet_'.$uid.'_body.json' ;
        $body=(is_object($msg))? $msg->body:$msg['body'] ;
        file_put_contents($temp_fname_body,$body) ;
	 }
	 else
	 {	 $temp_fname_body=_TEMP_DIR.'/rabbit_packet_'.$uid.'_body.json' ;
		 file_put_contents($temp_fname_body,json_encode($data,JSON_UNESCAPED_UNICODE)) ;
	 }

	 $rec_log=array('type'=>$props['type'],
                 'message_id'=>$props['message_id'],
                 'direct'=>$direct,
                 'status'=>$status,
                 'content'=>$comment,
                 'uid'=>$uid) ;

	 if ($options['trip_id']) $rec_log['trip_id']=$options['trip_id'] ;
	 if ($data['trip_id']) $rec_log['trip_id']=$data['trip_id'] ;

   	 $log_rec_id=adding_rec_to_table('log_rabbit',$rec_log) ;

   }
}
?>