<?php

require_once HORDE_BASE . '/lib/Serialize.php';
require_once HORDE_BASE . '/lib/Kolab.php';
require_once HORDE_BASE . '/lib/iCalendar.php';
require_once 'Net/HTTP/Client.php';

/**
 * Moment storage implementation for the Kolab server.
 *
 * Copyright 2003 Code Fusion, cc.
 *
 * Required values for $params:<pre>
 *      'server'        The database type (e.g. 'pgsql', 'mysql', etc.).
 *      'folder'        The hostname of the database server.
 *
 * @author  Stuart Bingė <s.binge@codefusion.co.za>
 * @version $Revision: 0.1 $
 * @since   Moment 1.0
 * @package moment
 */
class Moment_Driver_kolab extends Moment_Driver {

    /** Hash containing connection parameters. */
    var $_params = array();
    var $_folder;
    var $_server;

    /**
     * Constructs a new Kolab storage object.
     *
     * @param string $organizer The user who organized these meetings.
     * @param array  $params    A hash containing connection parameters.
     */
    function Moment_Driver_kolab($organizer, $params = array())
    {
        $this->_organizer = $organizer;
        $this->_params = $params;
        $this->_server = array_key_exists('server', $params) ? $params['server'] : 'localhost';
        $this->_folder = array_key_exists('folder', $params) ? $params['folder'] : 'INBOX/Calendar';
    }

    function retrieve()
    {
        $imap = Kolab::OpenImapConnection($this->_server, $this->_folder);
        if (!$imap) return PEAR::raiseError('Unable to open IMAP connection.');

        $this->_meetings = array();

        $msgs = Kolab::GetMessageList($imap);
        $cal = new Horde_iCalendar;
        for ($i = 0; $i < count($msgs); $i++)
        {
            $body = imap_body($imap, $msgs[$i]);
            $cal->parsevCalendar($body);

            $components = $cal->getComponents();
            $ispresent = false;

            foreach ($components as $component)
            {
                if (!is_a($component, 'Horde_iCalendar_vevent')) continue;

                $startattr = $component->getAttribute('DTSTART');
                if (is_array($startattr) || is_a($startattr, 'PEAR_Error')) continue;

                $meeting = array();

                $meeting['message_id']  = $msgs[$i];
                $meeting['id']          = (!PEAR::isError($tmp = $component->getAttribute('UID')) ? $tmp : '');
                $meeting['organizer']   = (!PEAR::isError($tmp = $component->getAttribute('ORGANIZER')) ? $tmp : '');
                $meeting['title']       = (!PEAR::isError($tmp = $component->getAttribute('SUMMARY')) ? $tmp : '');
                $meeting['description'] = (!PEAR::isError($tmp = $component->getAttribute('DESCRIPTION')) ? $tmp : '');
                $meeting['location']    = (!PEAR::isError($tmp = $component->getAttribute('LOCATION')) ? $tmp : '');
                $meeting['start']       = (!PEAR::isError($tmp = $component->getAttribute('DTSTART')) ? $tmp : 0);
                $meeting['end']         = (!PEAR::isError($tmp = $component->getAttribute('DTEND')) ? $tmp : 0);
                $meeting['attendees']   = array();
                $meeting['uid']         = (!PEAR::isError($tmp = $component->getAttribute('UID')) ? $tmp : '');
                $meeting['sequence']    = (!PEAR::isError($tmp = $component->getAttribute('SEQUENCE')) ? $tmp : 0);
                $meeting['status']      = 1;
                $meeting['flags']       = 0;

                $atnames = $component->getAttribute('ATTENDEE');
                $atparms = $component->getAttribute('ATTENDEE', true);

                if (is_array($atnames)) {
                    foreach ($atnames as $attendee) {
                        $meeting['attendees'][] = array(
                            'email' => str_replace('mailto:', '', $attendee),
                            'attendance' => 'required',
                            'responce' => 'none'
                        );
                    }
                } else if (!PEAR::isError($atnames)) {
                    $meeting['attendees'][] = array(
                        'email' => str_replace('mailto:', '', $atnames),
                        'attendance' => 'required',
                        'responce' => 'none'
                    );
                }

                $this->_meetings[$meeting['uid']] = $meeting;
            }
        }

        Kolab::CloseIMAPConnection($imap);

        return true;
    }

    function store()
    {
        $added_meetings = $this->listMeetings(MEETING_ADDED);
        $modified_meetings = $this->listMeetings(MEETING_MODIFIED);
        $deleted_meetings = $this->listMeetings(MEETING_DELETED);

        if ((count($added_meetings) == 0) && (count($modified_meetings) == 0) &&
            (count($deleted_meetings) == 0)) {
            return true;
        }

        $imap = Kolab::OpenImapConnection($this->_server, $this->_folder);
        if (!$imap) return PEAR::raiseError('Unable to open IMAP connection.');

        list($user, $pass) = Kolab::GetAuthentication();
        $mailbox = Kolab::MailboxURI($this->_server, $this->_folder);

        $cal = new Horde_iCalendar;

        foreach ($added_meetings as $meeting_id => $meeting) {
            var_dump($meeting['attendees']);

            $evobj = &$cal->addNewComponent('VEVENT');

            $evobj->setAttribute('CREATED', time());
            $evobj->setAttribute('UID', $meeting_id);
            $evobj->setAttribute('SUMMARY', $meeting['title']);
            $evobj->setAttribute('DESCRIPTION', $meeting['description']);
            $evobj->setAttribute('LOCATION', $meeting['location']);
            $evobj->setAttribute('LAST-MODIFIED', time());
            $evobj->setAttribute('ORGANIZER', $this->_organizer);
            $evobj->setAttribute('DTSTART', $meeting['start']);
            $evobj->setAttribute('DTEND', $meeting['end']);
            $evobj->setAttribute('SEQUENCE', $meeting['sequence']);

            foreach ($meeting['attendees'] as $attendee) {
                $evobj->setAttribute('ATTENDEE', 'mailto:' . $attendee['email'], array(
                        'RSVP' => 'FALSE',
                        'PARTSTAT' => 'ACCEPTED',
                        'ROLE' => 'REQ-PARTICIPANT'
                    ), true);
            }

            $this->setFlag($meeting_id, MEETING_ADDED, false);

            $body = str_replace("\n", MIME_NL, $cal->exportvCalendar());
            if (!Kolab::AddMessage($imap, $mailbox, $user, 'text/calendar', $body, 'Moment', array(
                    'Subject' => $meeting_id
                ))) {
                Kolab::CloseIMAPConnection($imap);
                return PEAR::raiseError('Unable to add meeting.');
            }
            $cal->clear();
        }

        foreach ($modified_meetings as $meeting_id => $meeting)
        {
            $mid = $meeting['message_id'];
            if (is_null($mid)) continue;
            $cal->parsevCalendar(imap_body($imap, $mid));
            @imap_delete($imap, $mid);

            $evobj = &$cal->findComponent('VEVENT');
            if (!$evobj) {
                Kolab::CloseIMAPConnection($imap);
                return PEAR::raiseError('Unable to modify meeting.');
            }

            $evobj->setAttribute('SUMMARY', $meeting['title']);
            $evobj->setAttribute('DESCRIPTION', $meeting['description']);
            $evobj->setAttribute('LOCATION', $meeting['location']);
            $evobj->setAttribute('LAST-MODIFIED', time());
            $evobj->setAttribute('DTSTART', $meeting['start']);
            $evobj->setAttribute('DTEND', $meeting['end']);

            $evobj->clearAttribute('ATTENDEE');
            foreach ($meeting['attendees'] as $attendee) {
                $evobj->setAttribute('ATTENDEE', 'mailto:' . $attendee['email'], array(
                        'RSVP' => 'FALSE',
                        'PARTSTAT' => 'ACCEPTED',
                        'ROLE' => 'REQ-PARTICIPANT'
                    ), true);
            }

            $body = str_replace("\n", MIME_NL, $cal->exportvCalendar());
            if (!Kolab::AddMessage($imap, $mailbox, $user, 'text/calendar', $body, 'Nag', array(
                    'Subject' => $evobj->getAttribute('UID')
                ))) {
                Kolab::CloseIMAPConnection($imap);
                return PEAR::raiseError('Unable to modify task.');
            }

            $this->setFlag($meeting_id, MEETING_MODIFIED, false);
        }

        foreach ($deleted_meetings as $meeting_id => $meeting)
        {
            $mid = $meeting['message_id'];
            if (is_null($mid)) continue;
            @imap_delete($imap, $mid);

            $this->setFlag($meeting_id, MEETING_DELETED, false);
        }

        $this->purgeDeleted();

        Kolab::CloseIMAPConnection($imap);

        return true;
    }

}
