<?php
/**
 * DokuWiki Plugin criticmarkup (Syntax Component)
 *
 * Jednoduchá podpora Critic Markup syntaxe:
 *
 *  {++vložený text++}         -> <ins>vložený text</ins>
 *  {--smazaný text--}         -> <del>smazaný text</del>
 *  {==zvýrazněný text==}      -> <mark>zvýrazněný text</mark>
 *  {~~původní~>nový~~}        -> <del>původní</del><ins>nový</ins>
 *  {>>komentář<<}             -> <span class="critic-comment">komentář</span>
 */

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

class syntax_plugin_criticmarkup extends DokuWiki_Syntax_Plugin {

    public function getType() {
        return 'formatting';
    }

    public function getPType() {
        return 'normal';
    }

    public function getSort() {
        return 199;
    }

    /**
     * Registrace vzorů pro všechny režimy
     */
    public function connectTo($mode) {
        $this->Lexer->addSpecialPattern('\{\+\+.*?\+\+\}', $mode, 'plugin_criticmarkup'); // insert
        $this->Lexer->addSpecialPattern('\{\-\-.*?\-\-\}', $mode, 'plugin_criticmarkup'); // delete
        $this->Lexer->addSpecialPattern('\{==.*?==\}',   $mode, 'plugin_criticmarkup');  // mark
        $this->Lexer->addSpecialPattern('\{~~.*?~~\}',   $mode, 'plugin_criticmarkup');  // substitution
        $this->Lexer->addSpecialPattern('\{>>.*?<<\}',   $mode, 'plugin_criticmarkup');  // comment
    }

    /**
     * Rozparsování nalezeného zápisu
     */
    public function handle($match, $state, $pos, Doku_Handler $handler) {
        // $match je např.:
        // "{++text++}", "{--text--}", "{==text==}", "{~~old~>new~~}", "{>>comment<<}"

        // druh podle prvních dvou znaků po '{'
        $marker = substr($match, 1, 2);
        $type   = null;

        switch ($marker) {
            case '++':
                $type = 'ins';
                break;
            case '--':
                $type = 'del';
                break;
            case '==':
                $type = 'mark';
                break;
            case '~~':
                $type = 'subst';
                break;
            case '>>':
                $type = 'comment';
                break;
            default:
                return null;
        }

        // odřízneme počáteční "{++"/"{--"/"{=="/"{~~"/"{>>" (3 znaky)
        // a koncové "++}"/"--}"/"==}"/"~~}"/"<<}" (3 znaky)
        $inner = substr($match, 3, -3);

        if ($type === 'subst') {
            // {~~původní~>nový~~}
            $parts = explode('~>', $inner, 2);
            $old = isset($parts[0]) ? $parts[0] : '';
            $new = isset($parts[1]) ? $parts[1] : '';

            return array(
                'type' => 'subst',
                'old'  => $old,
                'new'  => $new,
            );
        }

        return array(
            'type' => $type,
            'text' => $inner,
        );
    }

    /**
     * Generování výsledného XHTML
     */
    public function render($mode, Doku_Renderer $R, $data) {
        if ($mode !== 'xhtml') {
            return false;
        }

        if ($data === null || !is_array($data)) {
            return false;
        }

        $type = $data['type'];

        switch ($type) {
            case 'ins':
                $R->doc .= '<ins>';
                $R->cdata($data['text']);
                $R->doc .= '</ins>';
                break;

            case 'del':
                $R->doc .= '<del>';
                $R->cdata($data['text']);
                $R->doc .= '</del>';
                break;

            case 'mark':
                $R->doc .= '<mark>';
                $R->cdata($data['text']);
                $R->doc .= '</mark>';
                break;

            case 'subst':
                // {~~old~>new~~} -> <del>old</del><ins>new</ins>
                $old = isset($data['old']) ? $data['old'] : '';
                $new = isset($data['new']) ? $data['new'] : '';

                if ($old !== '') {
                    $R->doc .= '<del>';
                    $R->cdata($old);
                    $R->doc .= '</del>';
                }
                if ($new !== '') {
                    $R->doc .= '<ins>';
                    $R->cdata($new);
                    $R->doc .= '</ins>';
                }
                break;

            case 'comment':
                // {>>komentář<<} -> <span class="critic-comment">komentář</span>
                $R->doc .= '<span class="critic-comment">';
                $R->cdata($data['text']);
                $R->doc .= '</span>';
                break;

            default:
                return false;
        }

        return true;
    }
}
