<?php

// Actions
/** @const MNEMO_ADD_MEMO Add a new memo.           */ define('MNEMO_ADD_MEMO', 101);
/** @const MNEMO_DELETE_MEMOS Delete memos.         */ define('MNEMO_DELETE_MEMOS', 102);
/** @const MNEMO_MODIFY_MEMO Modify a memo.         */ define('MNEMO_MODIFY_MEMO', 103);
/** @const MNEMO_SAVE_MEMO Save a memo to storage.  */ define('MNEMO_SAVE_MEMO', 104);
/** @const MNEMO_SEARCH_MEMOS Search the memo list. */ define('MNEMO_SEARCH_MEMOS', 105);
/** @const MNEMO_DELETE_CATEGORY Delete a category. */ define('MNEMO_DELETE_CATEGORY', 106);
/** @const MNEMO_RENAME_CATEGORY Rename a category. */ define('MNEMO_RENAME_CATEGORY', 107);
/** @const MNEMO_ADD_CATEGORY Add a new category.   */ define('MNEMO_ADD_CATEGORY', 108);

// Sort types
/** @const MNEMO_SORT_DESC Sort by memo description.    */ define('MNEMO_SORT_DESC', 0);
/** @const MNEMO_SORT_CATEGORY Sort by memo category.   */ define('MNEMO_SORT_CATEGORY', 1);
/** @const MNEMO_SORT_ASCEND Sort in ascending order.   */ define('MNEMO_SORT_ASCEND', 0);
/** @const MNEMO_SORT_DESCEND Sort in descending order. */ define('MNEMO_SORT_DESCEND', 1);

/**
 * Mnemo Base Class.
 *
 * $Horde: mnemo/lib/Mnemo.php,v 1.24 2003/06/19 18:47:52 chuck Exp $
 *
 * @author Jon Parise <jon@horde.org>
 * @version $Revision: 1.24 $
 * @package mnemo
 */
class Mnemo {

    /**
     * Retrieves the current user's memo list from storage.
     * This function will also sort the resulting list, if requested.
     *
     * @param object Mnemo_Driver  $storage      The current storage object.
     * @param constant $criteria (optional) A set of flags specifying the set of
     *                           memos to return. (MEMO_ANY, MEMO_ADDED,
     *                           MEMO_MODIFIED, MEMO_DELETED)
     * @param constant $sortby   (optional) The field by which to sort.
     *                           (MNEMO_SORT_DESC, MNEMO_SORT_CATEGORY)
     * @param constant $sortdir  (optional) The direction by which to sort.
     *                           (MNEMO_SORT_ASC, MNEMO_SORT_DESC)
     *
     * @return array        Returns a list of the requested memos.
     *
     * @see Mnemo_Driver::listMemos()
     */
    function listMemos($criteria = MEMO_ANY, $sortby = MNEMO_SORT_DESC,
                       $sortdir = MNEMO_SORT_ASCEND)
    {
        global $conf;
        $memos = array();

        /* Sort the memo list. */
        $sort_functions = array(
            MNEMO_SORT_DESC => 'ByDesc',
            MNEMO_SORT_CATEGORY => 'ByCategory'
        );

        foreach ($GLOBALS['display_notepads'] as $notepad) {
            /* Create a Mnemo storage instance. */
            $storage = &Mnemo_Driver::singleton($conf['storage']['driver'], $notepad,
                                                $conf['storage']['params']);
            $storage->retrieve();

            /* Retrieve the memo list from storage. */
            $newmemos = $storage->listMemos();
            $memos = array_merge($memos, $newmemos);
        }

        /* Sort the array if we have a sort function defined for this field. */
        if (isset($sort_functions[$sortby])) {
            $prefix = ($sortdir == MNEMO_SORT_DESCEND) ? '_rsort' : '_sort';
            uasort($memos, array('Mnemo', $prefix . $sort_functions[$sortby]));
        }

        return $memos;
    }

    /**
     * Retrieve a specific memo from storage.
     *
     * @param string $meomlist  The notepad to retrieve the memo from.
     * @param string $memo      The Id of the memo to retrieve.
     *
     * @return array            The memo.
     */
    function getMemo($notepad, $memo)
    {
        global $conf;

        $storage = &Mnemo_Driver::factory($conf['storage']['driver'], $notepad,
                                          $conf['storage']['params']);
        $storage->retrieve();

        $allmemos = $storage->listMemos();

        if (array_key_exists($memo, $allmemos)) {
            return $allmemos[$memo];
        }

        return false;
    }

    /**
     * List all memo lists a user has access to.
     *
     * @param optional boolean $owneronly  Only return memo lists that this
     *                                     user owns? Defaults to false.
     * @param optional integer $permission The permission to filter notepads by.
     *
     * @return array  The memo lists.
     */
    function listNotepads($owneronly = false, $permission = _PERMS_SHOW)
    {
        $notepads = $GLOBALS['mnemo_shares']->listShares(Auth::getAuth(), $permission, $owneronly);
        if (is_a($notepads, 'PEAR_Error')) {
            Horde::logMessage($notepads, __FILE__, __LINE__, PEAR_LOG_ERR);
            return array();
        }

        return $notepads;
    }

    /**
     * Builds the HTML for a memo category widget.
     *
     * @param string  $name       The name of the widget.
     * @param integer $selected   (optional) The default category.
     * @param boolean $newheader  (optional) Include a new new category option.
     *
     * @return string       The HTML <select> widget.
     */
    function buildCategoryWidget($name, $selected = false, $newheader = false)
    {
        $html = "<select name=\"$name\">";

        if ($newheader) {
            $html .= '<option value="*new*">' . _("New Category") . "</option>\n";
            $html .= '<option value="">----' . "</option>\n";
        }

        foreach (Mnemo::listCategories() as $id => $name) {
            $html .= "<option value=\"$id\"";
            $html .= ($id == $selected && $selected !== false) ? ' selected="selected">' : '>';
            $html .= $name . '</option>';
        }
        $html .= '</select>';

        return $html;
    }

    /**
     * List a user's categories
     *
     * @return array A list of categories.
     */
    function listCategories($notepad = null)
    {
        global $prefs;

        static $catString, $categories;

        $cur = $GLOBALS['mnemo_shares']->getPrefByShare('memo_categories', $notepad);
        if (is_null($catString) || $catString != $cur) {
            $categories = array(0 => _("Unfiled"));

            $catString = $cur;
            if (empty($catString)) {
                return $categories;
            }

            $cats = explode('|', $catString);
            foreach ($cats as $cat) {
                list($key, $val) = explode(':', $cat);
                $categories[$key] = $val;
            }
        }

        asort($categories);
        return $categories;
    }

    /**
     * Add a new category
     *
     * @param string  $name     The name of the category to add.
     *
     * @return integer          A valid category id, 0 on failure or
     *                          the new category's id on success.
     *
     * @since Mnemo 1.1
     */
    function addCategory($name)
    {
        global $prefs;

        if ($prefs->isLocked('memo_categories') || empty($name)) {
            return 0;
        }

        $categories = Mnemo::listCategories();

        if (in_array($name, $categories)) {
            return 0;
        }

        $categories[] = $name;
        unset($categories[0]);

        $cats = array();
        $key = 0;
        foreach ($categories as $key => $cat) {
            $cat = array($key, $cat);
            $cats[] = implode(':', $cat);
        }

        $catString = implode('|', $cats);
        $prefs->setValue('memo_categories', $catString);

        return $key;
    }

    /**
     * Delete a category
     *
     * @param integer   $categoryID The id of the category to remove.
     *
     * @return boolean              True on success, false on failure.
     *
     * @since Mnemo 1.1
     */
    function deleteCategory($categoryID)
    {
        global $prefs;
        $categories = Mnemo::listCategories();

        if ($prefs->isLocked('memo_categories') || !array_key_exists($categoryID, $categories)) {
            return false;
        }

        unset($categories[0]);
        unset($categories[$categoryID]);

        $cats = array();
        foreach ($categories as $key => $cat) {
            $cat = array($key, $cat);
            $cats[] = implode(':', $cat);
        }

        $catString = implode('|', $cats);
        $prefs->setValue('memo_categories', $catString);

        return true;
    }

    /**
     * Rename a category
     *
     * @param integer   $categoryID The id of the category to remove.
     * @param string    $name       The new name of the category.
     *
     * @return boolean              True on success, false on failure.
     *
     * @since Mnemo 1.1
     */
    function renameCategory($categoryID, $name)
    {
        global $prefs;
        $categories = Mnemo::listCategories();

        if ($prefs->isLocked('memo_categories') || empty($name) ||
                        !array_key_exists($categoryID, $categories)) {
            return false;
        }

        unset($categories[0]);
        $categories[$categoryID] = $name;

        $cats = array();
        foreach ($categories as $key => $cat) {
            $cat = array($key, $cat);
            $cats[] = implode(':', $cat);
        }

        $catString = implode('|', $cats);
        $prefs->setValue('memo_categories', $catString);

        return true;
    }


    /**
     * Returns the highlight colors for the categories
     *
     * @return array A list of colors, key matches listCategories keys.
     *
     * @since Mnemo 1.1
     */
    function categoryColors()
    {
        global $prefs;

        static $colorString, $colors;

        if (!isset($colors) || $colorString != $prefs->getValue('memo_colors')) {
            $colorString = $prefs->getValue('memo_colors');
            $cols = explode('|', $colorString);
            $colors = array(0 => "#ffffff");
            foreach ($cols as $col) {
                list($key, $val) = explode(':', $col);
                $colors[$key] = $val;
            }
        }
        return $colors;
    }

    /**
     * Returns the string matching the given category ID.
     *
     * @param integer $categoryID     The category ID to look up.
     * @param string  $notepad        The notepad the category belongs to.
     *
     * @return string       The formatted category string.
     */
    function formatCategory($categoryID = 0, $notepad = null)
    {
        $categories = Mnemo::listCategories($notepad);
        return isset($categories[$categoryID]) ?
            $categories[$categoryID] :
            $categories[0];
    }

    /**
     * Comparison function for sorting memos by description.
     *
     * @param array $a  Memo one.
     * @param array $b  Memo two.
     *
     * @return integer  1 if memo one is greater, -1 if memo two is greater; 0 if they are equal.
     */
    function _sortByDesc($a, $b)
    {
        return strcasecmp($a['desc'], $b['desc']);
    }

    /**
     * Comparison function for reverse sorting memos by description.
     *
     * @param array $a  Memo one.
     * @param array $b  Memo two.
     *
     * @return integer  -1 if memo one is greater, 1 if memo two is greater; 0 if they are equal.
     */
    function _rsortByDesc($a, $b)
    {
        return strcasecmp($b['desc'], $a['desc']);
    }

    /**
     * Comparison function for sorting memos by category.
     *
     * @param array $a  Memo one.
     * @param array $b  Memo two.
     *
     * @return integer  1 if memo one is greater, -1 if memo two is greater; 0 if they are equal.
     */
    function _sortByCategory($a, $b)
    {
        return strcasecmp(Mnemo::formatCategory($a['category'], $a['memolist_id']),
                          Mnemo::formatCategory($b['category'], $b['memolist_id']));
    }

    /**
     * Comparison function for reverse sorting memos by category.
     *
     * @param array $a  Memo one.
     * @param array $b  Memo two.
     *
     * @return integer  -1 if memo one is greater, 1 if memo two is greater; 0 if they are equal.
     */
    function _rsortByCategory($a, $b)
    {
        return strcasecmp(Mnemo::formatCategory($b['category'], $b['memolist_id']),
                          Mnemo::formatCategory($a['category'], $a['memolist_id']));
    }

    function menu()
    {
        global $notification, $conf, $registry, $prefs, $print_link, $browser;
        $notepads = Mnemo::listNotepads();

        require_once HORDE_BASE . '/lib/Menu.php';
        require MNEMO_TEMPLATES . '/menu/menu.inc';

        /* Include the JavaScript for the help system (if enabled). */
        Help::javascript();

        // Check here for guest notepads so that we don't get multiple
        // messages after redirects, etc.
        if (!Auth::getAuth() && !count(Mnemo::listNotepads())) {
            $notification->push(_("No notepads are available to guests."));
        }

        $notification->notify();
    }

}
