"""
$URL: svn+ssh://sting.mems-exchange.org/repos/trunk/DurusWorks/proto/lib/ui/qwiki.qpy $
$Id: qwiki.qpy 32785 2010-09-15 22:23:23Z dbinger $
"""
from durus.btree import BTree
from durus.persistent import Persistent
from qp.fill.directory import Directory
from qp.fill.form import Form
from qp.fill.html import href
from qp.lib.spec import add_getters_and_setters, string, specify
from qp.pub.common import get_publisher
from qp.pub.common import header, footer, redirect, page
from qpy import xml
import re

word_pattern = re.compile(r'\b\w+\b')

class Text(Persistent):

    value_is = string

    def __init__(self, value=None):
        specify(self, value=value or '')

    def get_words(self):
        return set(word_pattern.findall(self.value))

add_getters_and_setters(Text)


def get_wiki_map():
    root = get_publisher().get_root()
    wiki_map = root.get('wiki_map')
    if wiki_map is None:
        root['wiki_map'] = BTree()
        wiki_map = root.get('wiki_map')
    return wiki_map


class QwikiDirectory (Directory):

    def get_exports(self):
        yield ('', 'index', 'qwiki', 'The QWiki Wiki')

    def _q_lookup(self, component):
        if component.strip():
            return WikiPageUI(component.strip())

    def index:xml(self):
        header('QWiki Pages')
        '<ul>'
        for name in sorted(get_wiki_map().iterkeys()):
            '<li>%s</li>' % href(name, name)
        '</ul>'
        form = Form(use_tokens=False)
        form.add_string('new', title='Page to Edit:')
        if form.get('new'):
            try:
                form.get('new').encode('ascii')
            except UnicodeEncodeError:
                form.set_error('new', 'Must use ascii characters.')
            else:
                redirect(form.get('new') + '/edit')
        form.render()
        footer()

class WikiPageUI (Directory):

    def __init__(self, name):
        self.name = name
        self.wiki_page = get_wiki_map().get(name) or Text()

    def get_exports(self):
        yield ('', 'index', self.name, None)
        yield ('edit', 'edit', 'Edit', 'Edit this wiki page.')
        yield ('delete', 'delete', 'Delete', 'Delete this wiki page.')

    def index(self):
        is_wiki_name = get_wiki_map().get
        text = xml.quote(self.wiki_page.get_value())
        for word in self.wiki_page.get_words():
            if is_wiki_name(word):
                text = re.sub(r'\b(%s)\b' % word,
                              href("../" + word, word),
                              text)
        return page(self.name, xml(text), directory=self)

    def edit(self):
        form = Form()
        form.add_text('text', title="Text", value=self.wiki_page.get_value(),
                      cols=70, rows=10)
        form.add_submit('submit', value="Submit")
        form.add_submit('cancel', value="Cancel")
        if form.get('cancel'):
            redirect('.')
        if not form.is_submitted() or form.has_errors():
            return page(self.name, form.render())
        self.wiki_page.set_value(form.get('text') or '')
        if self.name not in get_wiki_map():
            get_wiki_map()[self.name] = self.wiki_page
        redirect('.')

    def delete(self):
        form = Form()
        form.add_submit('delete', value="Delete")
        form.add_submit('cancel', value="Cancel")
        if form.get('cancel'):
            redirect('.')
        if not form.is_submitted():
            return page("Delete %s?" % self.name,
                        self.wiki_page.get_value(),
                        form.render())
        if self.name in get_wiki_map():
            del get_wiki_map()[self.name]
        redirect('..')
