<?php
require_once('./websockets.php');
require_once("../../scriptel-easyscript.phar");

/**
 * This class implements a very simple multi-user signature listener server.
 */
class SignatureServer extends WebSocketServer {
    /**
     * Keeps track of per-session user data.
     */
    public $userData = array();

    /**
     * This is called when the web socket recieves data.
     */
    protected function process($user, $message) {
        for($i = 0; $i < strlen($message); $i++) {
            $chr = substr($message, $i, 1);
            //The library expects line-feeds, not carrage returns.
            if($chr == "\r") { $chr = "\n"; }
            try {
                $this->userData[$user->id]['easyscript']->parseCharacter($chr);
            } catch(SignatureInvalidException $e) {
                $this->send($user, json_encode($e));
            }
        }
    }

    /**
     * This is called when a web socket connects.
     */
    protected function connected($user) {
        $easyScript = new \com\scriptel\EasyScript();
        $easyScript->addListener(new SignatureListener($user, $this));

        $this->userData[$user->id] = array();
        $this->userData[$user->id]['user'] = $user;
        $this->userData[$user->id]['easyscript'] = $easyScript;
    }

    /**
     * This is called when a web socket closes.
     */
    protected function closed($user) {
        unset($this->userData[$user->id]);
    }

    /**
     * This function provides a wrapper for send(), since it's protected.
     */
    public function sendWrapper($user, $msg) {
        $this->send($user, $msg);
    }
}

/**
 * This class is a per-websocket signature listener that listens for events.
 */
class SignatureListener implements \com\scriptel\EasyScriptEventListener {
    /**
     * The web socket we're listening on behalf of.
     */
    private $user;
    /**
     * Our parent server that can send messages over the websocket.
     */
    private $server;

    /**
     * Constructor, takes the user and server information and saves it for later.
     */
    public function __construct($user, $server) {
        $this->user = $user;
        $this->server = $server;
    }

    /**
     * Gets a coordinate from the EasyScript library.
     */
    public function receiveCoordinate($coordinate) {
        $coord = array("_class"=>"Coordinate", "x"=>$coordinate->getX(), "y"=>$coordinate->getY());
        $this->server->sendWrapper($this->user, json_encode($coord));
    }

    /**
     * Gets a new stroke from the EasyScript library.
     */
    public function newStroke() {
        $this->server->sendWrapper($this->user, json_encode(array("_class"=>"NewStroke")));
    }

    /**
     * Gets a cancel message from the EasyScript library.
     */
    public function cancel() {
        $this->server->sendWrapper($this->user, json_encode(array("_class"=>"Cancel")));
    }

    /**
     * Gets a end of signature message from the EasyScript library.
     */
    public function endOfSignature() {
        $this->server->sendWrapper($this->user, json_encode(array("_class"=>"EndOfSignature")));
    }

    /**
     * Gets a signature meta data message from the EasyScript library.
     */
    public function signatureMetaData($metaData) {
        $md = array(
            "_class"=>"SignatureMetaData",
            "protocolVersion"=>$metaData->getProtocolVersion(),
            "model"=>$metaData->getModel(),
            "version"=>$metaData->getVersion()
        );
        $this->server->sendWrapper($this->user, json_encode($md));
    }

    /**
     * Gets a card swipe from the EasyScript library.
     */
    public function cardSwipe($swipe) {
        $swipe = array(
            "_class"=>"CardSwipe",
            "protocolVersion"=>$swipe->getProtocolVersion(),
            "cardData"=>$swipe->getCardData(),
            "info"=>$swipe->toString()
        );
        $this->server->sendWrapper($this->user, json_encode($swipe));
    }
}

//Initializes the signature server.
$sig = new SignatureServer("0.0.0.0","9000");
try {
    //Starts the server.
    $sig->run();
} catch (Exception $e) {
    print_r($e);
}
?>