#format python
"""
MoinMoin macro to create a list of current users
UserList.py
ark  06/13/04  0.1

    ***********
    by Antti Kuntsi <antti@kuntsi.com>
    As far as the author is concerned, this code is released to the public
    domain, but some restrictions in the MoinMoin COPYING file may apply. Ask a
    lawyer.
    _parse_arguments -method from ImageLink.py by jkk
    ***********
    This code has not been tested exhaustively. Use at your own risk.
    This code opens the userdict.pickle, and if it gets corrupted, you have a
    problem. You have been warned.
    The multiple column support has not been tested, but is assumed to be
    working.
    ***********

    This macro displays a list of currently known users.

    Usage:
        [[UserList]]
    [[UserList(column1, column2, ...)]]

    Demo. Try pasting the above examples into a MoinMoin sandbox page.


"""


import string, pickle, time
from math import ceil
from MoinMoin import wikiutil, config

def sorted_users(users):
    usernames=users.keys()
    usernames.sort()
    for username in usernames:
        usertime = time.localtime(float(users[username].split(".")[0]))
        yield username, usertime

def execute(macro, args):
    '''handle the UserList Macro. return the generated display HTML
    ark  06/13/04'''
    # parse the arguments
    if args==None:
        args = ''
    parseargs = _parse_arguments(args, ',', '"')
    columnlist=[]
    if len(parseargs)>0:
        columnlist=filter(None, [name.strip() for name in parseargs])

    result = [macro.formatter.paragraph(0)]
    userdict = pickle.load(file(config.data_dir+"/user/userdict.pickle"))

    if not userdict:
        return

    userlist = sorted_users(userdict)

    if columnlist:
            columnsize=int(ceil(len(userdict)/float(len(columnlist))))
    
    initials = []
    initial=''
    currentcount=0
    for name, creationtime in userlist:
        if initial != name[0]:
            initial=name[0]
            initials.append(initial)
            if currentcount:
                result.append(macro.formatter.bullet_list(0))
            if columnlist and (currentcount > columnsize or currentcount == 0):
                newcolumn=columnlist.pop(0)
                if currentcount:
                    result.append(macro.formatter.rawHTML('</div>'))
                result.append(macro.formatter.rawHTML('<div id="%s">'%newcolumn))
        result.append(macro.formatter.anchordef(initial))
        result.append(macro.formatter.heading(2, name[0]))
        result.append(macro.formatter.bullet_list(1))
        result.append(macro.formatter.listitem(1))
        name = macro.formatter.pagelink(name, name)
        result.append("%s -- %s"%(name, time.strftime(config.date_fmt, creationtime)))
        result.append(macro.formatter.listitem(0))
        currentcount+=1
    
    result.append(macro.formatter.bullet_list(0))
    if parseargs:
        result.append(macro.formatter.rawHTML('</div>'))
    while columnlist:
        result.append(macro.formatter.rawHTML('<div id="%s">&nbsp;</div>'%columnlist.pop(0)))
    anchorlinks = "".join([macro.formatter.anchorlink(a, a) for a in initials])
    result.append(macro.formatter.paragraph(1))
    result.append(macro.formatter.rawHTML('<br clear="both">'))
    result.insert(0, anchorlinks)
    result.append(anchorlinks)
    return "\n".join(result)


def _parse_arguments(argstring, delimchar=',', quotechar='"'):
    '''parse argstring into separate arguments originally separated by delimchar.
    occurrences of delimchar found within quotechars are ignored.
    This parser is not particularly elegant. Improvements are welcome.
    jjk  03/28/01'''
    # replace delimiters not in quotes with a special delimiter
    delim2 = chr(0)
    inquote = 0
    for i1 in range(len(argstring)):
        cchar = argstring[i1]
        if cchar==quotechar:
            inquote = not inquote
        elif (not inquote) and cchar==delimchar:
            argstring = argstring[:i1] + delim2 + argstring[i1+1:]
    # split the argument string on the special delimiter, and remove external quotes
    args = string.split(argstring, delim2)
    for i1 in range(len(args)):
        arg = args[i1]
        if arg[:1]==quotechar and arg[-1:]==quotechar:
            args[i1] = arg[1:-1]
    return args


