<?php
if(!defined('DOKU_INC')) die();
if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC.'lib/plugins/');

require_once(DOKU_PLUGIN.'action.php');

class action_plugin_calendoku extends DokuWiki_Action_Plugin {
    function register(&$controller) {
        $controller->register_hook('IO_WIKIPAGE_WRITE', 'BEFORE', $this, 'handle_pagewrite');
        $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handle_deliverical');
    }

    function handle_deliverical(&$event, $param) {
        if (!is_string($event->data) || strcmp($event->data, 'ical'))
            return;
        $INFO = pageinfo();

        $namespaces = preg_split('/\s/', $this->getconf('icalnamespaces'));
        $dohandle = false;
        foreach ($namespaces as $namespace)
            if (!strcmp($INFO['namespace'], $namespace)) {
                $dohandle = true;
                break;
            }
        if (!$dohandle)
            return;

        if (auth_quickaclcheck($INFO['id']) < AUTH_READ)
            return;

        header('Content-type: text/calendar');
        header('Content-disposition: attachment; filename="'.$INFO['id'].'.ics"');
        die(file_get_contents($INFO['filepath']));
    }

    function handle_pagewrite(&$event, $param) {
        /* data[3] is false for the current page, set to revision otherwise. */
        if ($event->data[3])
            return;

        if (!strcmp($this->getConf('icalnamespaces'), ''))
            return;

        /* Namespace. false if root ns. */
        if (!isset($event->data[1]))
            return;

        $templates = preg_split('/\s/', $this->getConf('icaltemplates'));
        foreach ($templates as $template)
            if (!strcmp($template, $event->data[2]))
                return;

        $dohandle = false;
        $namespaces = preg_split('/\s/', $this->getConf('icalnamespaces'));
        foreach ($namespaces as $namespace)
            if (!strcmp($event->data[1], $namespace)) {
                $dohandle = true;
                break;
            }
        if (!$dohandle)
            return;

        $event->data[0][1] = $this->reparseTemplateWrite($event->data[0][1]);
    }

    function reparseTemplateWrite($text) {
        // XXX: BEGIN:VCALENDAR
        $textlines = preg_split('/\n/', $text);
        $newtext = '';

        $inparse = false;
        $now = new DateTime('now');
        foreach ($textlines as $line) {
            /* Get DTSTAMP or LAST-MODIFIED. They have to be changed. */
            if (!$inparse && (preg_match('/^(DTSTAMP:)/', $line, $match)
                    || preg_match('/^(LAST-MODIFIED:)/', $line, $match))) {
                $newtext .= $match[1].$now->format('Ymd').'T'.$now->format('His')."\n";
                continue;
            }

            /* Get datetime lines, i.e. YYYY-MM-DD hh:mm. */
            if (!$inparse && preg_match('/^([[:alnum:]-]*?):@@([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9-]{1,2}):([0-9-]{1,2})@@$/', $line, $match)) {
                if (!strcmp($match[5], '-') || !strcmp($match[6], '-')) {
                    $newtext .= $match[1].':'.$match[2].$match[3].$match[4]."\n";
                } else {
                    if (count($match[5]) == 1)
                        $match[5] = '0'.$match[5];
                    if (count($match[6]) == 1)
                        $match[6] = '0'.$match[6];
                    $newtext .= $match[1].':'.$match[2].$match[3].$match[4].'T'.$match[5].$match[6].'00'."\n";
                }
                continue;
            }

            /* Single-line field. */
            if (!$inparse && preg_match('/^([[:alnum:]-]*?):@@(.*)@@$/', $line, $match)) {
                $newtext .= $match[1].':'.$match[2]."\n";
                continue;
            }

            /* Start of some added field. */
            if (!$inparse && preg_match('/^([[:alnum:]-]*?):@@(.*)$/', $line, $match)) {
                $newtext .= $match[1].':'.$match[2]."\n";
                $inparse = true;
                continue;
            }

            /* End of a field. */
            if ($inparse && preg_match('/^(.*)@@$/', $line, $match)) {
                $newtext .= ' '.$match[1]."\n";
                $inparse = false;
                continue;
            }

            /* In the middle of some added field. */
            if ($inparse) {
                $newtext .= ' '.$line."\n";
                continue;
            }

            /* Nothing found. */
            $newtext .= $line."\n";
        }

        /* Remove trailing newline. */
        $newtext = substr($newtext, 0, -1);

        return $newtext;
    }
}

// vim:ts=4:sw=4:et:enc=utf-8:
