<?php

require_once(__DIR__.'/vendor/autoload.php');
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Connection\AMQPSSLConnection;
use PhpAmqpLib\Message\AMQPMessage;


$lineReadTimeout=1;

$port=getenv("SCANNER_PORT");
$rabbitHost=getenv("RABBITMQ_HOST");
$rabbitPort=getenv("RABBITMQ_PORT")?getenv("RABBITMQ_PORT"):5672;
$rabbitLogin=getenv("RABBITMQ_USER");
$rabbitPass=getenv("RABBITMQ_PASSWORD");
$rabbitUseSSL=getenv("RABBITMQ_USE_SSL")==="true";
$rabbitVirtualHost=getenv("RABBITMQ_VIRTUAL_HOST")?getenv("RABBITMQ_VIRTUAL_HOST"):"/";
$routingTag=getenv("DEFAULT_TAG")?getenv("DEFAULT_TAG"):null;

$connection=null;
$channel=null;


while (1) {
    try {
        $connection=rabbitConnect($rabbitHost, $rabbitPort, $rabbitLogin, $rabbitPass, $rabbitUseSSL);
        $channel=$connection->channel();
        scanner($channel, $port);
    } catch (Exception $e) {
        print "Exception ".$e->getMessage()."\n";
        $channel->close();
        $connection->close();
        $s=rand(5, 15);
        print "Sleep $s seconds..";
        sleep($s);
        print "Ok\n";
    }
}

function rabbitConnect($rabbitHost, $rabbitPort, $rabbitLogin, $rabbitPass, $rabbitUseSSL=false, $rabbitVirtualHost="/") {
    if ($rabbitUseSSL) {
        $ssl_opts=[
            // set some SSL/TLS specific options
            'verify_peer' => true,
            'verify_peer_name' => true,
            'allow_self_signed' => false
        ];
    
        $connection = new AMQPSSLConnection($rabbitHost, $rabbitPort, $rabbitLogin, $rabbitPass, $rabbitVirtualHost, $ssl_opts);
    } else {
        $connection = new AMQPStreamConnection($rabbitHost, $rabbitPort, $rabbitLogin, $rabbitPass, $rabbitVirtualHost);
    }
    return $connection;
}

function register($channel, $routingTag) {
    print "Register\n";
    if (!empty($routingTag)) {
        $msg = new AMQPMessage(json_encode(["type"=>"service","data"=>"register"]));
        $channel->basic_publish($msg, 'fox.barcode', $routingTag);
    }
}

function scanner($channel, $port) {
    global $routingTag;

    $fp = @fopen($port, "rb+");
    if ($fp==null) {
        throw new Exception("Scanner failed. Is it connected?");
    } else {
        print "Scanner connected\n";
        if (!empty($routingTag)) {
            $msg = new AMQPMessage(json_encode(["type"=>"service","data"=>"scannerReady"]));
            $channel->basic_publish($msg, 'fox.barcode', $routingTag);
        }

    }
    
    while (1) {
        $buffer = fgets($fp, 4096);
        $rv=explode("\n", $buffer);
        if ($buffer === false) {
            if (!empty($routingTag)) {
                $msg = new AMQPMessage(json_encode(["type"=>"service","data"=>"scannerFailed"]));
                $channel->basic_publish($msg, 'fox.barcode', $routingTag);
            }
            throw new Exception("Stream read failed. Scanner disconnected?");
        }
        
        if (preg_match('/^fxc([0-9a-f]{20})xf$/', $buffer, $ref)) {
            print "Pairing request. Routing tag: $ref[1]\n";
            $routingTag=$ref[1];
            $msg = new AMQPMessage(json_encode(["type"=>"service","data"=>"scannerRegistered"]));
            $channel->basic_publish($msg, 'fox.barcode', $routingTag);

        } else {
            print "Read: $rv[0]";
            if (!empty($routingTag)) {
                $msg = new AMQPMessage(json_encode(["type"=>"code","data"=>$rv[0]]));
                $channel->basic_publish($msg, 'fox.barcode', $routingTag);
            
                print " [S]";
            } else {
                print " [-]";
            }
            print "\n";
        }
    }
}