<?php
/**
 * Gil Plugin: Shows currency equivalents
 * 
 * @file       gil/syntax.php
 * @brief      Shows currency equivalents
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author     Luis Machuca B. <luis.machuca [at] gulix.cl>
 * @author     Sridhar Kuppalli (concept) <sridhar.kuppalli [at] gmail.com>
 * @version    0.4
 * 
 *
 *  This plugin's purpose is to display a monetary value with currency 
 *  (eg.: CLP$5 000) and provide equivalencies for other currencies 
 *  (eg.: = US$8,9 or AUD$11).
 *
 *  This is a plugin currently intended for **testing only**.
 *  Only a basic form of caching is implemented and no check is done
 *  with regards to the validity of currency units.
 *
 *  Original idea by Sridhar Koppalli, a developer who shows in his blog:
 *  "Get Live currency value from yahoo server" (available at
 * http://kuppalli.wordpress.com/2008/11/15/get-live-currency-value-using-yahoo-api/)
 *  how to do just that using some PHP. I just adapted the literal code
 *  to work within DokuWiki.
 *
 *  Greetings.
 *        - Luis Machuca Bezzaza, 'ryan.chappelle' in the Wiki
 * 
 */

if(!defined('DW_LF')) define('DW_LF',"\n");
 
if(!defined('DOKU_INC')) 
define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
if(!defined('DOKU_PLUGIN')) 
define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
require_once(DOKU_PLUGIN.'syntax.php');
 
/**
 * All DokuWiki plugins to extend the parser/rendering mechanism
 * need to inherit from this class
 */
class syntax_plugin_gil extends DokuWiki_Syntax_Plugin {

    /**
     * Constructor. Checks for connectivity.
     */
    function syntax_plugin_gil(){
      //if(!fsockopen($this->_request_uri(),80)) {
      //  }
      $conn = @file_get_contents ($this->_request_uri(), 0, 0, 0, 128);
      if ($conn===false) msg('Gil Plugin: '. $this->getLang('e_nodatasrc'). '.',-1);
      }

    /**
     * return some info
     */
    function getInfo(){
      return array(
            'author' => 'Luis Machuca Bezzaza',
            'email'  => 'luis.machuca [at] gulix.cl',
            'date'   => @file_get_contents(DOKU_PLUGIN . 'gil/VERSION'),
            'name'   => 'Gil Plugin',
            'desc'   => $this->getLang('descr'),
            'url'    => 'http://www.dokuwiki.org/plugin:gil',
      );
    }
 
    /**
     * What kind of syntax are we?
     */
    function getType(){
      return 'substition';
    }
 
    /**
     * What can we Do?
     */
    function getAllowedTypes() { 
       return array(); 
    }
 
    /**
     * Where to sort in?
     */
    function getSort(){
      return 599;
    }
 
    /**
     * What's our code layout?
     */    
    function getPType(){ 
      return 'normal'; 
    }
 
    /**
     * How do we get to the lexer?
     */
    function connectTo($mode) {
      // extended syntax (for different source currency)
      $this->Lexer->addSpecialPattern (
        '\$\$[A-Z]{3}[0-9]+(?:[\.,][0-9]+)?', $mode, 'plugin_gil');
      // standard syntax
      $this->Lexer->addSpecialPattern (
        '\$\$[0-9]+(?:[\.,][0-9]+)?', $mode, 'plugin_gil');

 
    }
 
    /**
     * Handle the match
     */
    function handle($match, $state, $pos, &$handler){
      static $conversions;
      // check the structure of the match: 
      $match = substr($match, 2);
      //$cLocale= setlocale(LC_ALL, 0);

      // get the plugin configuration (source and target)
      $sc    = $this->getConf('gil_source');
      $tc    = $this->getConf('gil_targets');

      // if the first character is a letter, we are looking for a
      // different source currency in the first 3 characters
      if (ctype_upper($match[0])) {
        $oc    = $sc; // original source
        $sc    = substr($match, 0, 3);
        $match = substr($match, 3);
        // add original currency to targets to show
        $tc    = $oc. ','. $tc;
        }

      // prepare targets and perform conversions
      $tc      = explode(',', $tc);
      foreach ($tc as $T) {
        // request calculation
        if (!isset($conversions[$sc][$T]) ) {
          $tcfactor= $this->_get_curfactor($sc, $T) ;
          $conversions[$sc][$T] = $tcfactor;
          }
        }
      // finally, assemble the $data variable
      $data= array (
                  'state'   => $state,
                  'match'   => $match,
                  'source'  => $sc,
                  'cnvs'    => $conversions
                  );

      return $data;
    }  
 
    /**
     * Create output
     */
    function render($mode, &$renderer, $data) {
      /* get the data from $data */
      $source_expr= $data['source']. '$'. $data['match'];
      $convs= $data['cnvs'];

      if ($mode == 'xhtml') {
        /* the nature of this plugin should require cache disabling */
        $renderer->info['cache'] = false;
        $title_expr     = "Gil conversions for $source_expr.";
        $cnv_expr       = $this->_do_conv_text($convs, $data['match'], $data['source']);
        $renderer->doc .= <<<EOF
<span class="gil" title="$title_expr">$source_expr <span data="gil:conversions" class="tooltip">$cnv_expr</span></span>
EOF;
        return true;
        }
      else if ($mode == 'text') {
        /* here we simply throw the conversions together */
        $renderer->doc.= $source_expr;
        $renderer->doc.= ' '. $this->_do_conv_text($convs, $data['match']);
        $renderer->doc.= ' ';
        return true;
        }
      return false;
    }

    /**
     * from this point onwards, helper functions
     */


    /**
     * @fn     _get_curfactor
     * @brief  Obtains the currency conversion factor
     *
     * This is pretty much Sridhar's original work.
     */
    function _get_curfactor ($sc, $tc) {
      $hpool= '';
      $query= $this->_request_uri();
      $query= str_replace('$1', $sc, $query);
      $query= str_replace('$2', $tc, $query);
      // request the data conversion sheet
      $handle= @fopen($query, 'r');
      if (!$handle) {
        //printf ($this->getLang('e_nodatasrc'));
        $ans= 'N/A';
        }
      else {
        $hpool= fgets($handle, 2048);
        // retrieve the latest data
        if (empty($hpool) ) {
          // error handling is not yet appropiate
          $ans= '?';
          }
        else {
          $matches= explode (',', $hpool);
          $factor= $matches[1];
          $ans= floatval($factor);
          }
        } // end process input
      fclose($handle);
      return $ans;
      } // end function


    /**
     * @fn     _do_conv_text
     * @brief  Creates a single text string from the conversions $convs.
     *
     */
    function _do_conv_text ($convs, $a, $sc) {
      $text= ''; 
      $ctext= array();
      foreach ($convs[$sc] as $K => $M) {
        $ctext[]= "$K". ' '. $M*$a;
        }
      // join everything into a single string
      $text= '( '. implode(' | ', $ctext). ' )';
      return $text;
      } // end function

    function _request_uri () {
      static $url= 'http://finance.yahoo.com/d/quotes.csv?e=.csv&f=sl1d1t1&s=$1$2=X';
      return $url;
      }


}
