#!/usr/bin/env php
<?php
/**
 * Copyright 2003-2013 Horde LLC (http://www.horde.org/)
 *
 * See the enclosed file COPYING for license information (LGPL). If you
 * did not receive this file, see http://www.horde.org/licenses/lgpl21.
 *
 * @author Chuck Hagenbuch <chuck@horde.org>
 */

if (file_exists(__DIR__ . '/../../kronolith/lib/Application.php')) {
    $baseDir = __DIR__ . '/../';
} else {
    require_once 'PEAR/Config.php';
    $baseDir = PEAR_Config::singleton()
        ->get('horde_dir', null, 'pear.horde.org') . '/kronolith/';
}
require_once $baseDir . 'lib/Application.php';
Horde_Registry::appInit('kronolith', array('cli' => true));

send_agendas();

/**
 */
function send_agendas()
{
    if (isset($_SERVER['REQUEST_TIME'])) {
        $runtime = $_SERVER['REQUEST_TIME'];
    } else {
        $runtime = time();
    }

    $kronolith_shares = $GLOBALS['injector']->getInstance('Kronolith_Shares');
    $calendars = $kronolith_shares->listAllShares();

    // If there are no calendars to check, we're done.
    if (!count($calendars)) {
        return;
    }

    if (empty($GLOBALS['conf']['reminder']['server_name']) ||
        empty($GLOBALS['conf']['reminder']['from_addr'])) {
        die('You must configure the server_name and from_addr settings for reminders in the calendar configuration.');
    }

    $_SERVER['SERVER_NAME'] = $GLOBALS['conf']['server']['name'] = $GLOBALS['conf']['reminder']['server_name'];

    // Retrieve a list of users associated with each calendar, and
    // thus a list of users who have used kronolith and
    // potentially have an agenda preference set.
    $users = array();
    foreach (array_keys($calendars) as $calendarId) {
        try {
            $calendar = $kronolith_shares->getShare($calendarId);
        } catch (Exception $e) {
            continue;
        }
        $users = array_merge($users, $calendar->listUsers(Horde_Perms::READ));
    }

    // Remove duplicates.
    $users = array_unique($users);

    // Generate image mime part first and only once, because we need
    // the Content-ID.
    $image = Kronolith::getImagePart('big_agenda.png');

    $runtime = new Horde_Date($runtime);
    $default_timezone = date_default_timezone_get();
    $kronolith_driver = Kronolith::getDriver();
    $view = new Horde_View(array('templatePath' => KRONOLITH_TEMPLATES . '/agenda', 'encoding' => 'UTF-8'));
    new Horde_View_Helper_Text($view);
    $view->imageId = $image->getContentId();
    $view->date = $runtime;
    if (!$GLOBALS['prefs']->isLocked('daily_agenda')) {
        $view->prefsUrl = Horde::url($GLOBALS['registry']->getServiceLink('prefs', 'kronolith'), true)->remove(session_name());
    }

    // Loop through the users and generate an agenda for them
    foreach ($users as $user) {
        $prefs = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Prefs')->create('kronolith', array(
            'user' => $user
        ));
        $agenda_calendars = $prefs->getValue('daily_agenda');

        if (!$agenda_calendars) {
            continue;
        }

        // Try to find an email address for the user.
        $identity = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Identity')->create($user);
        $email = $identity->getDefaultFromAddress(true);

        // Check if user has a timezone pref, and set it. Otherwise, make
        // sure to use the server's default timezone.
        $tz = $prefs->getValue('timezone');
        date_default_timezone_set(empty($tz) ? $default_timezone : $tz);

        // If we found an email address, generate the agenda.
        switch ($agenda_calendars) {
        case 'owner':
            $calendars = $kronolith_shares->listShares(
                $user,
                array('perm' => Horde_Perms::SHOW,
                      'attributes' => $user));
            $calendars = array_keys($calendars);
            break;

        case 'read':
            $calendars = $kronolith_shares->listShares(
                $user,
                array('perm' => Horde_Perms::READ));
            $calendars = array_keys($calendars);
            break;

        case 'show':
        default:
            $calendars = array();
            $shown_calendars = unserialize($prefs->getValue('display_cals'));
            $cals = $kronolith_shares->listShares(
                $user,
                array('perm' => Horde_Perms::SHOW));
            foreach (array_keys($cals) as $calId) {
                if (in_array($calId, $shown_calendars)) {
                    $calendars[] = $calId;
                }
            }
        }

        // Get a list of events for today
        $eventlist = array();
        foreach ($calendars as $calId) {
            $kronolith_driver->open($calId);
            $events = $kronolith_driver->listEvents(
                $runtime, $runtime, array('show_recurrence' => true));
            foreach ($events as $dayevents) {
                foreach ($dayevents as $event) {
                    // The event list contains events starting at 12am.
                    if ($event->start->compareDate($runtime)) {
                        continue;
                    }
                    $eventlist[] = $event;
                }
            }
        }

        if (!count($eventlist)) {
            continue;
        }

        // If there are any events, generate and send the email.
        usort($eventlist, 'sort_events');
        $GLOBALS['registry']->setLanguageEnvironment($prefs->getValue('language'));
        $twentyFour = $prefs->getValue('twentyFour');

        $view->pad = max(Horde_String::length(_("All day")) + 2, $twentyFour ? 6 : 8);
        $view->dateFormat = $prefs->getValue('date_format');
        $view->timeformat = $twentyFour  ? 'H:i' : 'h:ia';
        $view->user = $user;
        $view->events = $eventlist;

        $mime_mail = new Horde_Mime_Mail(array(
            'Subject' => sprintf(_("Your daily agenda for %s"), $runtime->strftime($view->dateFormat)),
            'To' => $email,
            'From' => $GLOBALS['conf']['reminder']['from_addr'],
            'User-Agent' => 'Kronolith ' . $GLOBALS['registry']->getVersion(),
            'Auto-Submitted' => 'auto-generated'));
        try {
            $mime_mail->addRecipients($email);
        } catch (Horde_Mime_Exception $e) {}

        $mime_mail->setBasePart(Kronolith::buildMimeMessage($view, 'notification', $image));

        Horde::logMessage(sprintf('Sending daily agenda to %s', $email), 'DEBUG');
        try {
            $mime_mail->send($GLOBALS['injector']->getInstance('Horde_Mail'));
        } catch (Horde_Mime_Exception $e) {
            Horde::logMessage(sprintf('Error sending daily agenda to %s: %s', $email, $e->getMessage()), 'WARN');
        }
    }
}

function sort_events ($a, $b)
{
    if ($a->allday && $b->allday) {
        return 0;
    }

    if ($a->allday || $b->allday) {
        return ($a->allday) ? -1 : 1;
    }

    if ($a->start == $b->start) {
        return 0;
    }

    return ($a->start < $b->start) ? -1 : 1;
}
