<?php

/**
 * this class is used when we want to publish a request to the AdminIn broker.  The class wraps all of the
 * RabbitMQ initialization and communication work so you don't have to.  Especially useful for unit testing.
 *
 *
 * @author  mike@givingassistant.org
 * @version 1.0
 *
 * HISTORY:
 * ========
 * 06-15-17     mks     original coding
 * 07-05-17     mks     eliminated recursive calls to the $logger entity; replaced $logger calls with console output
 *
 */

use /** @noinspection PhpUnusedAliasInspection */ PhpAmqpLib\Connection\AMQPStreamConnection;
use /** @noinspection PhpUnusedAliasInspection */ PhpAmqpLib\Channel\AMQPChannel;
use PhpAmqpLib\Exception\AMQPTimeoutException;
use /** @noinspection PhpUnusedAliasInspection */ PhpAmqpLib\Message\AMQPMessage;

class gacAdminClientIn
{
    /** @var PhpAmqpLib\Connection\AMQPStreamConnection */
    private $rabbitConnection;
    /** @var  PhpAmqpLib\Channel\AMQPChannel */
    private $rabbitChannel;
    private $rabbitCorrelationID;
    private $rabbitCallbackQueue;
    private $queueName;
    private $res = 'BACI: ';        // Broker Admin Client In
    public $status;

    /**
     * __construct() -- public method
     *
     * this is the constructor for the class.  it requests an admin resource from the resource manager and declares
     * a client-side connection to the service.
     *
     * there is an optional input parameter -- $_fw (from-where) that inserts a string into the queue label allowing
     * easy identification of the requesting source.
     *
     * the method returns no values.  It only sets the class' status member variable, a Boolean, on success or fail,
     * accordingly.
     *
     *
     * @author  mike@givingassistant.org
     * @version 1.0
     *
     *
     * @param $_fw - "from where" - tweaks queue label to identify request origin
     *
     *
     * HISTORY:
     * ========
     * 06-15-17     mks     original coding
     *
     */
    public function __construct($_fw = 'AdminClientIn')
    {
        register_shutdown_function(array($this, STRING_DESTRUCTOR));
        $this->status = false;

        var_dump(debug_backtrace());
        $this->queueName = gasResourceManager::$cfgAdmin[CONFIG_BROKER_QUEUE_TAG] . BROKER_QUEUE_AI;
//        $this->rabbitConnection = gasResourceManager::fetchResource(RESOURCE_ADMIN);
        $this->rabbitConnection = new AMQPStreamConnection('localhost', 5672, 'namaste', 'oSZL8Cby', 'mdev');
        if (is_null($this->rabbitConnection)) return;
        $this->rabbitChannel = $this->rabbitConnection->channel();
        $label = uniqid('gacAdminInClient<' . $_fw . '>:');
        list($this->rabbitCallbackQueue, ,) = $this->rabbitChannel->queue_declare($label, false, false, false, false);  // was: f,f,f,t
        $this->status = true;
        return;
    }


    /**
     * call() -- public method
     *
     * This method is invoked outside of the class and is the entry point for publishing a message request to the
     * AdminIn broker.  It creates a new AMQP message and publishes it to the queue (defined in the constructor),
     * and then exits, returning a true message indicating that the messages was successfully published.
     *
     * Since the AdminIN broker is a fire-n-forget broker, there are no return messages to block-and-wait on.
     *
     * If an exception is raised by this class, then a false value will be returned.
     *
     * NOTE: the true/false return values are not, in any way, a reflection of the processing success/failure on the
     * remote service.  The general RoT is that if we can publish the request, then we can only assume that the request
     * was successfully consumed and processed.
     *
     * @author  mike@givingassistant.org
     * @version 1.0
     *
     * @param $_data
     *
     * HISTORY:
     * ========
     * 06-15-17     mks     original coding
     *
     */
    public function call($_data)
    {
        $this->rabbitCorrelationID = uniqid();
        $res = false;
        $rabbitMessage = new AMQPMessage((string)$_data);
        try {
            $rabbitMessage = new AMQPMessage((string)$_data, array(BROKER_CORRELATION_ID => $this->rabbitCorrelationID, BROKER_REPLY_TO => $this->rabbitCallbackQueue));

            $this->rabbitChannel->basic_publish($rabbitMessage, '', $this->queueName);
            $res = true;
        } catch (AMQPTimeoutException $e) {
            echo getDateTime() . CON_ERROR . $this->res . ERROR_BROKER_EXCEPTION_TIMEOUT . PHP_EOL;
            echo getDateTime() . CON_ERROR . $this->res . $e->getMessage() . PHP_EOL;
        } catch (\PhpAmqpLib\Exception\AMQPRuntimeException $e) {
            echo getDateTime() . CON_ERROR . $this->res . ERROR_BROKER_EXCEPTION_RUNTIME . PHP_EOL;
            echo getDateTime() . CON_ERROR . $this->res . $e->getMessage() . PHP_EOL;
        } catch (AMQPException $e) {
            echo getDateTime() . CON_ERROR . $this->res . ERROR_BROKER_EXCEPTION . PHP_EOL;
            echo getDateTime() . CON_ERROR . $this->res . $e->getMessage() . PHP_EOL;
        } catch (Exception $e) {
            echo getDateTime() . CON_ERROR . $this->res . ERROR_BROKER_EXCEPTION . PHP_EOL;
            echo getDateTime() . CON_ERROR . $this->res . $e->getMessage() . PHP_EOL;
        }
        $this->rabbitChannel->close();
        $this->rabbitConnection->close();
        $this->status = $res;
    }


    public function __destruct()
    {
        // As of PHP 5.3.10 destructors are not run on shutdown caused by fatal errors.
        //
        // destructor is registered shut-down function in constructor -- so any recovery
        // efforts should go in this method.
        if (is_object($this->rabbitChannel)) {
            $this->rabbitChannel->close();
            $this->rabbitConnection->close();
        }
    }
}