<?php
/**
 * TocTweak plugin for DokuWiki; Syntax metatoc
 * 
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author     Satoshi Sahara <sahara.satoshi@gmail.com>
 */

if(!defined('DOKU_INC')) die();

class syntax_plugin_toctweak_metatoc extends DokuWiki_Syntax_Plugin {

    protected $mode;
    protected $pattern = array(
        5 => '{{(?:METATOC|TOC)\b.*?}}',
    );
    protected $tocStyle = array(  // default toc visual design
        'METATOC' => 'toc_hierarchical',
        'TOC'     => 'toc_dokuwiki',
    );

    function __construct() {
        $this->mode = substr(get_class($this), 7); // drop 'syntax_' from class name
    }

    function getType() { return 'substition'; }
    function getPType(){ return 'block'; }
    function getSort() { return 30; }

    /**
     * Connect pattern to lexer
     */
    function connectTo($mode) {
        $this->Lexer->addSpecialPattern($this->pattern[5], $mode, $this->mode);
    }

    /**
     * Handle the match
     */
    function handle($match, $state, $pos, Doku_Handler $handler) {
        global $ID;

        // load helper object
        isset($tocTweak) || $tocTweak = $this->loadHelper($this->getPluginName());

        // Ex: {{METATOC 2-4 width18 toc_hierarchical >id#section | title}}

        preg_match('/^{{([A-Z]+)([>: ]?)/', $match, $m);
        $start = strlen($m[1]) +2;
        $param = substr($match, $start+1, -2);

        list($topLv, $maxLv, $tocClass, $tocTitle, $id) = $tocTweak->parse($param);

        $hash = strstr($id, '#');
        if ($id == $hash) { $id = $ID.$hash; }

        // should disable built-in TOC here?
        if ($m[1] == 'TOC') {
            $handler->_addCall('notoc', array(), $pos);
        }

        // check basic tocStyle
        if (!preg_match('/\btoc_.*\b/', $tocClass)) {
            $tocStyle = $this->tocStyle[$m[1]];
            $tocClass = implode(' ', array($tocStyle, $tocClass));
        }

        $data = array($id, $topLv, $maxLv, $tocClass, $tocTitle);
        return $data;
    }

    /**
     * Create output
     */
    function render($format, Doku_Renderer $renderer, $data) {
        global $INFO, $conf, $lang;

        list($id, $topLv, $maxLv, $tocClass, $tocTitle) = $data;
        list($id, $hash) = explode('#', $id);
        $section = $hash ? sectionID($hash, $check = false) : '';

        switch ($format) {
            case 'metadata':
                if ($id != $INFO['id']) { // current page
                    // set dependency info for PARSER_CACHE_USE event handler
                    $renderer->meta['relation']['toctweak'][] = metaFN($id,'.meta');
                }
                return true;

            case 'xhtml':
             // $renderer->info['cache'] = false; // disable xhtml cache

                // load helper object
                isset($tocTweak) || $tocTweak = $this->loadHelper($this->getPluginName());

                // retrieve TableOfContents from metadata
                $toc = $tocTweak->get_metatoc($id, $topLv, $maxLv, $section);
                if (empty($toc)) {
                    $toc[] = array(  // error entry
                        'hid'   => $section,
                        'page'  => $id,
                        'url'   => wl($id.'#'.$section),
                        'class' => 'wikilink2',
                        'title' => $id.'#'.$section,
                        'type'  => 'ul',
                        'level' => 1, 
                    );
                }

                // toc wrapper attributes
                $attr['class'] = $tocClass;
                $title = isset($tocTitle) ? $tocTitle : $lang['toc'];

                $html = '<!-- METATOC START -->'.DOKU_LF;
                $html.= '<div '.buildAttributes($attr).'>';
                $html.= $title ? '<h3>'.hsc($title).'</h3>' : '';
                $html.= '<div>';
                $html.= html_buildlist($toc, 'toc', array($this, 'html_list_metatoc'));
                $html.= '</div>';
                $html.= '</div>'.DOKU_LF;
                $html.= '<!-- METATOC END -->'.DOKU_LF;

                $renderer->doc .= $html;
                return true;
        }
    }

    /**
     * Callback for html_buildlist called from $this->render()
     * Builds html of each list item
     */
    function html_list_metatoc($item) {
        $html = '<span class="li">';
        if (isset($item['page'])) {
            $html.= '<a title="'.$item['page'].'#'.$item['hid'].'"';
            $html.= ' href="'.$item['url'].'" class="'.$item['class'].'">';
        } else {
            $html.= '<a href="#'.$item['hid'].'">';
        }
        $html.= hsc($item['title']).'</a>';
        $html.= '</span>';
        return $html;
    }

}