"""
    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.

    @copyright: 2006 by michael cohen <scudette@users.sourceforge.net>
    @license: GNU GPL, see COPYING for details.
"""
import re
from MoinMoin import config, wikiutil, search, 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 c,d: not c['regex'].search(d[c['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 c,d: c['regex'].search(d[c['column']])
            )

        return result

def match_conditions(conditions, d):
    """ Returns true if all conditions match, false if any fail to match """
    for c in conditions:
        if not c['func'](c,d):
            return False

    return True

def execute(macro, args):
    request = macro.request
    args = [a.strip() for a in args.split(',') ]
    conditions = []
    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
    for i in range(len(args)):
        c = parse_condition(args[i])
        if c:
            conditions.append(c)
            args[i]=None
        
    query = search.QueryParser(titlesearch=1).parse_query(needle)
    results = search.searchPages(request, query)
    results.sortByPagename()

    table = TupleDataset()
    table.columns = [  Column('', label='', align='right'), ] +[ 
        Column(x, label=x, align='right') for x in args if x ]

    ## Look at all the hits from our title filter
    for x in results.hits:
        d = wikidicts.Dict(request, x.page_name)
        
        ## Check to make sure that the conditons are matched
        if not match_conditions(conditions, d): continue

        ## Add the row to the table
        r = [ Page(request, x.page_name).link_to(request) ] + [ d.get(y,'') for y in args if y ]
        table.addRow(r)

    tmp = DataBrowserWidget(request)
    tmp.setData(table)
    tmp.render()

    return ''
