/**
 * agi_playSoundSet_read - play a soundset and read at least $min digit and
 *				maximum $max digit from the user. The user has
 *				to use the pound key in order to enter a 
 *				number of digit lower than the $maximum number
 *				of digit. 
 *
 * PRE: * $soundSetId : the Id of the soundset. If not found, return -1
 *	* $min the minimum number of digit. Below this number pound keu is 
 *		ignored
 *	* $max must be higher or equal to the minimum.
 * 	* $timeout : if the user doesn't enter any digit after $timeout seconds
 *			it replays the soundset.
 *	* $max_replay : maximum number of timeout --> return -1;
 *
 * POST:* plays the soundset and stops it after received the first digit
 *	* the star key replay the soundSet
 *	* return positive number = the value that the user enter
 *			 < 10^($max)-1
 *	        negative number : an error
 *	 	zero is a mositive number
 *	
 *	*    if the user enter 007, and that the minimum is 3, it's accepted
 *		but return an integer : 7
 */
function agi_play_soundSet_read($soundSetId, $min, $max, $timeout = 20, $max_replay = 3)
{
    $ndigits = 0;
    $result = 0;
    $tempRes = agi_play_soundSet($soundSetId);
    $max_replay--;
    if ($tempRes == 0) {
        // pas de digit lue, on fait une première pause
        // dans le but de ne pas faire entendre à l'utilisateur le
        // prompt immédiatement après
        $tempRes = agi_readDigit($timout);
    }
    while ($ndigits < $max) {
        if ($tempRes == -1) {
            return -1;
        } else {
            if ($tempRes == 0) {
                // pas de touche appuyée au bout du timeout
                // --> relecture
                $tempRes = agi_readDigit($timeout);
                if ($max_replay <= 0) {
                    return -1;
                }
                $tempRes = agi_play_soundSet($soundSetId);
                $max_replay--;
                if ($tempRes == 0) {
                    $tempRes = agi_readDigit($timout);
                }
                continue;
                // on reprend le parsing
            } else {
                if ($tempRes == 10) {
                    $tempRes = 0;
                } else {
                    if ($tempRes == "*") {
                        $tempRes = 0;
                        // force le timeout
                        continue;
                    } else {
                        if ($tempRes == "#") {
                            if ($ndigits >= $min) {
                                return $result;
                            } else {
                                $tempRes = 0;
                                continue;
                            }
                        }
                    }
                }
            }
        }
        // si nous sommes ici c'est que l'on a lu un chiffre correcte
        // et qu'il se trouve dans tempRes :
        $ndigits++;
        $result = $result * 10 + $tempRes;
        // on lance la lecture du nombre suivant :
        $tempRes = agi_readDigit($timout);
    }
    // nombre maximum de digit atteind :
    return $result;
}
function outside_dial(&$call)
{
    global $db;
    // 1°) trouver à quel réseau appartient l'extension
    $net = outside_getNetworkId($call);
    agi_log(DEBUG_DEBUG, 'outside_dial() : ' . $call->get_extension() . " -> {$net}");
    if ($net < 0) {
        return agi_notFound($call);
    }
    // 2°) faut-il annoncer le prix à l'utilisateur ?
    //	faut-il continuer plus cher ?
    $query = "select P.Announce, P.AskHigherCost " . "  from People_PrePay_Settings as P  " . " where People_Extension = " . $call->get_responsable();
    $query = $db->query($query);
    check_db($query);
    if (!($row = $query->fetchRow(DB_FETCHMODE_ORDERED))) {
        // not found : paramètre par défaut :
        $askHigher = false;
        $announce = true;
        agi_log(DEBUG_INFO, "outside_dial() : account not found");
    } else {
        $askHigher = $row[1];
        $announce = $row[0];
    }
    agi_log(DEBUG_DEBUG, "outside_dial() : {$announce} - {$askHigher}");
    // 3°) récupérer la liste des providers et leur prix
    $query = "select N.Name, N.channel, P.ConnectionPrice, P.Price, " . "       P.RmDigits, P.AddDigits, N.DialOpts " . " from  NetworkProvider as N, Price as P, " . "\t NetworkTimeZone_details as T " . " where P.Network_ID = {$net} " . "   and P.NetworkProvider_ID = N.ID " . "   and P.NetworkTimeZone_ID = T.NetworkTimeZone_ID " . "   and (" . date("i") . " between start_min and end_min )" . "   and (" . date("G") . " between start_hour and end_hour )" . "   and (" . date("n") . " between start_month and end_month )" . "   and (" . date("j") . " between start_dom and end_dom )" . "   and (" . date("w") . " between start_dow and end_dow )" . " order by P.Price, P.ConnectionPrice ";
    $query = $db->query($query);
    check_db($query);
    /*	0 : name	
     *	1 : channel
     *	2 : priceConn
     *	3 : price/min
     *	4 : RmDigits
     *	5 : AddDigits
     *	6 : DialOpts
     */
    if ($query->numRows() == 0) {
        return agi_notFound($call);
    }
    $provider = $query->fetchRow(DB_FETCHMODE_ORDERED);
    // 4°) on tente d'appeler
    $isFirst = true;
    // première tentative au prix le plus bas
    while (($isFirst || $askHigher) && $provider != NULL) {
        $price = $provider[3];
        // 5°) on annonce au besoin :
        if ($announce) {
            agi_play_soundSet(SOUNDSET_PRICE_ANNOUNCE, "");
            agi_sayNumber(ceil($price * 100));
            agi_play_soundSet(SOUNDSET_CURRENCY, "");
        }
        // on teste l'un à la suite de l'autre tout les providers
        // qui ont le même prix d'appel
        while ($provider[3] == $price && $provider != NULL) {
            $callStr = $provider[1] . $provider[5] . substr($call->get_extension(), $provider[4]);
            agi_log(DEBUG_DEBUG, "outside_dial() : trying : {$callStr}");
            $result = agi_call($call, $callStr, $provider[6], $provider[2], $provider[3], false);
            if ($result >= 0 || $call->get_lastTryStatus() != "CHANUNAVIL") {
                // succeed
                return $result;
            }
            $provider = $query->fetchRow(DB_FETCHMODE_ORDERED);
        }
        // annonce qu'il est impossible d'effectuer l'appel au prix
        // annoncé précédement
        agi_play_soundSet(SOUNDSET_UNAVAIL_AT_PRICE, "");
        $first = false;
        // téléchargement du provider suivant
        $provider = $query->fetchRow(DB_FETCHMODE_ORDERED);
    }
    agi_logCall($call, 0, 0, "NOT ROUTABLE");
    return -1;
}