<?php

/**
 * Classe utilizada para a comunicação com o Asterisk
 *
 * @author desenv
 *
 */
class AsteriskManagerAPI {

    private $msg300 = "Erro ao conectar ao servidor de telefonia";
    private $msg301 = "Erro de autenticação ao logar na telefonia";
    private $msg302 = "Erro ao iniciar a ligacao";
    private $msg400 = "Erro ao enviar sms";
    var $socket;
    var $error;
    var $sms_status;
    var $asterisk_confs;

    public function AsteriskManagerAPI() {
        $this->socket = false;
        $this->error = "";
        $this->asterisk_confs = Configure::read('Asterisk');
    }

    /**
     * Faz o login no Asterisk usando os dados
     * configurados no app_config.php
     *
     * @return boolean
     */
    public function login() {


        $host = $this->asterisk_confs['host'];
        $username = $this->asterisk_confs['username'];
        $password = $this->asterisk_confs['password'];


        $this->socket = @fsockopen($host, "5038", $errno, $errstr, 1);
        if (!$this->socket) {
            //$this->error =  "Could not connect - $errstr ($errno)";
            $this->error = $this->msg300;
            return false;
        } else {
            stream_set_timeout($this->socket, 1);

            $wrets = $this->Query("Action: Login\r\nUserName: $username\r\nSecret: $password\r\nEvents: off\r\n\r\n");
            if (strpos($wrets, "Message: Authentication accepted") != false) {
                return true;
            } else {
                //$this->error = "Could not login - Authentication failed";
                $this->error = $this->msg301;
                fclose($this->socket);
                $this->socket = false;
                return false;
            }
        }
    }

    /**
     * Faz o logout do Asterisk
     */
    public function logout() {
        if ($this->socket) {
            fputs($this->socket, "Action: Logoff\r\n\r\n");
            $wrets = "";
            while (!feof($this->socket)) {
                $wrets .= fread($this->socket, 8192);
            }
            fclose($this->socket);
            $this->socket = "true";
        }
        return;
    }

    /**
     * Executa um comando no Asterisk e retorna a saída do console
     *
     * ex.: $this->query("Action: Command\r\nCommand: sip show peers\r\n\r\n");
     *
     * @param unknown_type $query
     * @return boolean|unknown
     */
    public function query($query) {
        $wrets = "";

        if ($this->socket == false)
            return false;

        fputs($this->socket, $query);
        do {
            $line = fgets($this->socket, 4096);
            $wrets .= $line;
            $info = stream_get_meta_data($this->socket);
        } while ($line != "\r\n" && $info['timed_out'] == false);
        return $wrets;
    }

    /**
     * Busca pelos peers com seus respectivos status
     * @return multitype:
     */
    public function getPeers() {

        $this->login();

        $value = $this->query("Action: Command\r\nCommand: sip show peers\r\n\r\n");
        $this_array = preg_split("/\n/", $value);

        $peers = array();

        foreach ($this_array as $line) {
            if ((!strstr($line, "Response")) &&
                    (!strstr($line, "Privilege")) &&
                    (!strstr($line, "sip peers")) &&
                    (!strstr($line, "COMMAND")) &&
                    (!strstr($line, "Name"))) {

                array_push($peers, $line);
            }
        }

        $this->logout();
        return $peers;
    }

    /**
     * Executa uma ligação, recebe um array com os parâmetros
     * peer, exten, context, priority e async
     * @param unknown_type $params
     */
    public function call($params) {

        if (!$this->login()) {
            return false;
        }

        if ($this->socket) {

            fputs($this->socket, "Action: Originate\r\n" .
                    "Channel: " . $params['channel'] . "\r\n" .
                    "Exten: " . $params['exten'] . "\r\n" .
                    "Context: " . $params['context'] . "\r\n" .
                    "Variable: " . $params['variable'] . "\r\n" .
                    "priority: " . $params['priority'] . "\r\n\r\n" .
                    "Async: " . $params['async'] . "\r\n\r\n");

            $value = fgets($this->socket);

            if (strstr(strtoupper($value), 'ERROR')) {
                $this->error = $this->msg302;
                return false;
            }
        }

        $this->logout();
        return true;
    }

    /**
     * Envia um sms, recebe um array com os parâmetros
     * peer, exten, context, priority e async
     * @param unknown_type $params
     */
    public function sendsms($params) {

        $this->sms_status = "Fault";

        if (!$this->login()) {
            $this->sms_status = "Fault - $this->error ";
            return false;
        }

        if ($this->socket) {

            fputs($this->socket, "Action: KSendSMS\r\n" .
                    "Device: " . $params['channel'] . "\r\n" .
                    "Destination: " . $params['fone'] . "\r\n" .
                    "Confirmation: True\r\n" .
                    "Message: " . $params['message'] . "\r\n\r\n");

            $value = fgets($this->socket);

            if (strstr(strtoupper($value), 'ERROR')) {
                $this->error = $this->msg400;
                $this->sms_status = "Sms Failed - $value";
                $this->logout();
                return false;
            }
            $this->sms_status = "Success";
        } else {
            $this->sms_status = "Sms Failed - $this->error";
            $this->logout();
            return false;
        }

        $this->logout();
        return true;
    }

    /**
     * Retorna o erro gerado na classe
     */
    public function getError() {
        return $this->error;
    }

    /**
     * Retorna o status do envio de sms
     */
    public function getSmsStatus() {
        return $this->sms_status;
    }

}
