"""
    MoinMoin - PageDicts

    This macro uses the wikidicts mechanism for treating pages as dicts to
    then display a selection of pages in a table.

    Use it like this:
    [[PageDicts([!]Bug0, Description, Status, Status ~= open)]]

    This will draw a table with the columns pages, Description and
    Status for all pages whos titles match Bug0 with Status matching
    open. This can be used in many different scenarios, with
    appropriate templates.
    If you prefix the Bug0 with an !-mark, it will search for all user
    readable pages wich contain Bug0 (allowing for searching a categorie)
    Also note, that 'open' can be any valid regular expression (include pipes)

    @copyright: 2006 by michael cohen <scudette@users.sourceforge.net>
    @license: GNU GPL, see COPYING for details.
    History:
    0.4: made more usefull by allowing categories and catching some errors
         by Remco Boerma
    0.3: Fix typo, allow the "transpose" keyword to change the table layout
    0.2: original version
"""
import re
from MoinMoin import wikiutil,  search
from MoinMoin.datastruct import WikiDicts
from MoinMoin.Page import Page
from MoinMoin.util.dataset import TupleDataset, Column
from MoinMoin.widget.browser import DataBrowserWidget

Dependencies = ["pages"]

def parse_condition(arg):
    """ arg is a string which will be parsed into a condition dict.

    A condition is a way of enforcing a requirement on a dict d. For example:

    ## This will match if regex matches d['column_name']
    column_name ~= regex

    ## This will not match if regexp matches (inverse of above)
    column_name !~= regex
    """
    if '!~=' in arg:
        tmp = arg.split("!~=",1)
        result=dict(
            column= tmp[0].strip(),
            regex= re.compile(tmp[1].strip(), re.IGNORECASE),
            func = lambda condition,dictionary: not condition['regex'].search(dictionary[condition['column']])
            )

        return result
    elif '~=' in arg:
        tmp = arg.split("~=",1)
        result = dict(
            column = tmp[0].strip(),
            regex = re.compile(tmp[1].strip(), re.IGNORECASE),
            func = lambda condition,dictionary: condition['regex'].search(dictionary[condition['column']])
            )

        return result

def match_conditions(conditions, dictionary):
    """ Returns true if all conditions match, false if any fail to match """
    for condition in conditions:
        try:
	    if not condition['func'](condition,dictionary):
               return False
	except KeyError:
	    # Remco: prolly it's a template linking or anything, and this value is not available
	    return False

    return True

def execute(macro, args):
    request = macro.request
    args = [ arg.strip() for arg in args.split(',') ]
    conditions = []
    transpose = 0 ## if we transpose the results
    needle = args[0]
    if not needle:
        return macro.formatter.text("It is probably not a good idea to parse all pages as dicts? You must specify a title filter")

    try:
        args = args[1:]
    except IndexError:
        args = []

    ## Remove the args which are conditions and look for transpose flag
    for i in range(len(args)):
        condition = parse_condition(args[i])
        if condition:
            conditions.append(condition) # remco change
            args[i]=None
        elif 'transpose' in args[i]:
            transpose = 1
            args[i]=None


    # RemcoBoerma -- use internal search for finding the page: allows all contstructs to perform
    # the search... 
    results = [p.page_name for p in search.searchPages(request, needle, sort='page_name').hits]
    results = dict([(x,x) for x in results]).keys()
    #results.sort()
   
    table = TupleDataset()
    table.addRow( [ '', ] + [ arg for arg in args if arg ])

    ## Look at all the pages that matched our string
    for page in results:
        dictionary = WikiDicts(request).get(page)
        
        ## Check to make sure that the conditons are matched
        if not match_conditions(conditions, dictionary):
            continue

        ## Add the row to the table
        row = [ Page(request, page).link_to(request) ]
	cols = [ dictionary.get(column,'') for column in args if column ]
        
	## look if we have something in a column at all
	found = [ 1 for col in cols if col ]

	## only print the row if it has something
	if found:
        	table.addRow(row + cols)

    if transpose:
        ## transpose table (make column rows and rows columns)
        table.data = map(None, zip(*table.data))
    ## create the top columns
    table.columns = [ Column(col, label=col, align='right') for col in table.data[0] ]
    ## remove the row extracted as the column
    table.data = table.data[1:]
    tmp = DataBrowserWidget(request)
    tmp.setData(table)
    return tmp.render()
