<?php

require_once 'Horde/Template.php';

/**
 * This class represent a view of multiple free busy information sets.
 *
 * Copyright 2003-2005 Mike Cochrane <mike@graftonhall.co.nz>
 * Copyright 2004-2005 Jan Schneider <jan@horde.org>
 *
 * See the enclosed file COPYING for license information.
 *
 * $Horde: kronolith/lib/FBView.php,v 1.10.10.2 2005/01/19 16:14:17 jan Exp $
 *
 * @author  Mike Cochrane <mike@graftonhall.co.nz>
 * @author  Jan Schneider <jan@horde.org>
 * @package Kronolith
 */
class Kronolith_FreeBusy_View {

    var $_requiredMembers = array();
    var $_optionalMembers = array();

    var $_startHour;
    var $_endHour;

    var $_day;
    var $_startStamp;
    var $_endStamp;

    function addRequiredMember($vFreebusy)
    {
        $this->_requiredMembers[] = Util::cloneObject($vFreebusy);
    }

    function addOptionalMember($vFreebusy)
    {
        $this->_optionalMembers[] = Util::cloneObject($vFreebusy);
    }

    function render($day = null)
    {
        global $prefs;

        $this->_startHour = floor($prefs->getValue('day_hour_start') / 2);
        $this->_endHour = floor($prefs->getValue('day_hour_end') / 2);

        $this->_render($day);

        require_once 'Horde/iCalendar.php';
        $vCal = &new Horde_iCalendar();
        $required = &Horde_iCalendar::newComponent('vfreebusy', $vCal);
        foreach ($this->_requiredMembers as $member) {
            $required->merge($member, false);
        }
        $required->simplify();

        $optional = &Horde_iCalendar::newComponent('vfreebusy', $vCal);
        foreach ($this->_optionalMembers as $member) {
            $optional->merge($member, false);
        }
        $optional->simplify();

        $optimal = &Horde_iCalendar::newComponent('vfreebusy', $vCal);
        $optimal->merge($required, false);
        $optimal->merge($optional);

        $base_url = Horde::selfUrl();
        $base_url = Util::removeParameter($base_url, 'date');
        $base_url = Util::removeParameter($base_url, 'fbview');
        $base_url = Util::addParameter($base_url, 'fbview', $this->view);

        $template = &new Horde_Template();
        $template->set('title', $this->_title());

        $html = $template->fetch(KRONOLITH_TEMPLATES . '/fbview/header.tpl');

        $hours_html = $this->_hours();

        // set C locale to avoid localized decimal separators during CSS width
        // calculation.
        $lc = setlocale(LC_NUMERIC, 0);
        setlocale(LC_NUMERIC, 'C');

        // Required to attend.
        if (count($this->_requiredMembers) > 0) {
            $template = &new Horde_Template();
            $rows = '';
            foreach ($this->_requiredMembers as $member) {
                $blocks = $this->_getBlocks($member, $member->getBusyPeriods(), 'busyblock.tpl', _("Busy"));
                $template = &new Horde_Template();
                $template->set('blocks', $blocks);
                $template->set('name', $member->getName());
                $rows .= $template->fetch(KRONOLITH_TEMPLATES . '/fbview/row.tpl');
            }

            $template = &new Horde_Template();
            $template->set('title', _("Required to attend"));
            $template->set('rows', $rows);
            $template->set('hours', $hours_html);
            $html .= $template->fetch(KRONOLITH_TEMPLATES . '/fbview/section.tpl');
        }

        // Optional to attend.
        if (count($this->_optionalMembers) > 0) {
            $template = &new Horde_Template();
            $rows = '';
            foreach ($this->_optionalMembers as $member) {
                $blocks = $this->_getBlocks($member, $member->getBusyPeriods(), 'busyblock.tpl', _("Busy"));
                $template = &new Horde_Template();
                $template->set('blocks', $blocks);
                $template->set('name', $member->getName());
                $rows .= $template->fetch(KRONOLITH_TEMPLATES . '/fbview/row.tpl');
            }

            $template = &new Horde_Template();
            $template->set('title', _("Optional to attend"));
            $template->set('rows', $rows);
            $template->set('hours', $hours_html);
            $html .= $template->fetch(KRONOLITH_TEMPLATES . '/fbview/section.tpl');
        }

        // possible meeting times.
        $optimal->setAttribute('ORGANIZER', _("All Attendees"));
        $blocks = $this->_getBlocks($optimal,
                                    $optimal->getFreePeriods($this->_startStamp, $this->_endStamp),
                                    'meetingblock.tpl', _("All Attendees"));

        $template = &new Horde_Template();
        $template->set('name', _("All Attendees"));
        $template->set('blocks', $blocks);
        $rows = $template->fetch(KRONOLITH_TEMPLATES . '/fbview/row.tpl');

        // possible meeting times.
        $required->setAttribute('ORGANIZER', _("Required Attendees"));
        $blocks = $this->_getBlocks($required,
                                    $required->getFreePeriods($this->_startStamp, $this->_endStamp),
                                    'meetingblock.tpl', _("Required Attendees"));

        $template = &new Horde_Template();
        $template->set('name', _("Required Attendees"));
        $template->set('blocks', $blocks);
        $rows .= $template->fetch(KRONOLITH_TEMPLATES . '/fbview/row.tpl');

        // reset locale
        setlocale(LC_NUMERIC, $lc);

        $template = &new Horde_Template();
        $template->set('title', _("Possible Meeting Times"));
        $template->set('rows', $rows);
        $template->set('hours', $hours_html);
        $html .= $template->fetch(KRONOLITH_TEMPLATES . '/fbview/section.tpl');

        if ($prefs->getValue('show_fb_legend')) {
            $legend_html = Util::bufferOutput('require' , KRONOLITH_TEMPLATES . '/fbview/legend.inc');
        } else {
            $legend_html = '';
        }

        return array($html, $legend_html);
    }

    /**
     * Attempts to return a concrete Kronolith_FreeBusy_View instance based on
     * $view.
     *
     * @param string $view  The type of concrete Kronolith_FreeBusy_View
     *                      subclass to return.
     *
     * @return mixed  The newly created concrete Kronolith_FreeBusy_View
     *                instance, or false on an error.
     */
    function &factory($view)
    {
        $driver = basename($view);
        require_once dirname(__FILE__) . '/FBView/' . $view . '.php';
        $class = 'Kronolith_FreeBusy_View_' . $view;
        if (class_exists($class)) {
            return $ret = &new $class($user, $params);
        } else {
            return false;
        }
    }

    /**
     * Attempts to return a reference to a concrete Kronolith_FreeBusy_View
     * instance based on $view.  It will only create a new instance if no
     * Kronolith_FreeBusy_View instance with the same parameters currently
     * exists.
     *
     * This method must be invoked as:
     * $var = &Kronolith_FreeBusy_View::singleton()
     *
     * @param string $view  The type of concrete Kronolith_FreeBusy_View
     *                      subclass to return.
     *
     * @return mixed  The created concrete Kronolith_FreeBusy_View instance, or
     *                false on an error.
     */
    function &singleton($view)
    {
        static $instances;

        if (!isset($instances)) {
            $instances = array();
        }

        if (!isset($instances[$view])) {
            $instances[$view] = &Kronolith_FreeBusy_View::factory($view);
        }

        return $instances[$view];
    }

}
