# -*- coding: iso-8859-1 -*-
"""
    MoinMoin monobook theme.  Uses the css sheet from
    http://wikipedia.org, adapting the moin output to fit it.

    Adapted by Jim Clark <jim AT clarkster DOT co DOT uk>
    @license: GNU GPL, see COPYING for details.
"""

from MoinMoin.theme import ThemeBase
from MoinMoin import wikiutil, i18n
from MoinMoin.Page import Page

class Theme(ThemeBase):

    name = "monobook"

    # Standard set of style sheets
    stylesheets = (
        # media         basename
        ('all',         'common'),
        ('screen',      'monobook'),
        ('screen',      'screen'),
        ('print',       'print'),
        ('projection',  'projection'),
        )


# Public functions #####################################################

    def header(self, d, **kw):
        """ Assemble wiki header
        Here we don't add any menu bars, search bars, etc - instead wait
        until the footer.  This keeps the HTML cleaner and more accessible,
        making sure the main content arrives first.
        """
        html = [
            u'<div id="globalWrapper">',
            u'<div id="column-content">',
            self.startPage(),
            self.msg(d),
            self.title(d),
        ]
        return u'\n'.join(html)

    def footer(self, d, **keywords):
        """ Assemble wiki footer
        """
        html = [
            # End of page
            u'<div class="visualClear"></div>',
            self.endPage(),
            u'</div>',
            self.columnone(d),
            u'</div>'
            ]
        return u'\n'.join(html)

    def columnone(self, d):
        """ assemble all the navigation aids for the page
        """
        page = d['page']
        html = [
            u'<div id="column-one">',
            self.editbar(d),
            self.username(d),
            u'<div class="portlet" id="p-logo">',
            self.logo(),
            u'</div>',
            self.navibar(d),
            self.searchform(d),
            self.actionmenu(d),
            u'<div class="visualClear"></div>',
            u'<div id="footer">',
            self.pageinfo(page),
            self.credits(d),
            u'</div>',
            u'</div>'
            ]
        return u'\n'.join(html)

    def headscript(self, d):
        """ Override to not output search/action menu javascript.
        (perhaps not a good idea)
        """
        return ''

    def extendedAttrs(self, title, accesskey):
        """ Helper function for assembling titled access key links
        """
        return 'title="%(title)s [alt-%(accesskey)s]" accesskey=%(accesskey)s' % \
                     {'accesskey' : accesskey,
                      'title' : title}

    def editbar(self, d):
        """ Display a list of actions for the page.  This list will be turned
        into a set of tabbed views on the page by the css.
        """
        page = d['page']       
        if not self.shouldShowEditbar(page):
            return ''

        # Use cached editbar if possible.
        cacheKey = 'editbar'
        cached = self._cache.get(cacheKey)
        if cached:
            return cached

        request = self.request
        _ = self.request.getText
        link = wikiutil.link_tag
        quotedname = wikiutil.quoteWikinameURL(page.page_name)
        # action, title, description, accesskey
        tabs = [('show', 'Article', 'View the page content', 'c'),
                ('edit', 'Edit', 'Edit this page', 'e'),
                ('diff', 'Show Changes', 'Last page modification', 'd'),
                ('info', 'Get Info', 'Page history and information', 'h'),
                ('subscribe', 'Subscribe', 'Subscribe to updates to this page', 'w')]

        items = []
        current = self.request.form.get('action', ['show'])[0]
        for action, title, description, accesskey in tabs:
            if action == current:
                cls = 'selected'
            else:
                cls = 'none'

            if action == 'edit':
                if page.isWritable() and request.user.may.write(page.page_name):
                    pass
                else:
                    action = 'raw'
                    title = 'View Source'
                    description = 'This page is protected.  You can view its source'

            if action == 'subscribe':
                user = self.request.user
                if not self.cfg.mail_smarthost or not user.valid:
                    break
                # Email enabled and user valid, get current page status
                if user.isSubscribedTo([page.page_name]):
                    title = 'Unsubscribe'
                    description = 'Unsubscribe from updates to this page'
                    
            if action == 'show':
                url = quotedname
            else:
                url = quotedname + '?action=' + action
           
            attrs = self.extendedAttrs(_(description), accesskey)
            link = wikiutil.link_tag(self.request, url, _(title), attrs=attrs)
            items.append(u'<li class="%s">%s</li>' % (cls, link))

        html = [
            u'<div id="p-cactions" class="portlet">',
            u'<ul class="editbar">',
            ''.join(items),
            u'</ul>',
            u'</div>'
            ]
        html = ''.join(html)
        # cache for next call
        self._cache[cacheKey] = html

        return html


    def actionmenu(self, d):
        """ different implementation of the actionmenu (aka toolbox) 
        """

        page = d['page']

        # Use cached actionmenu if possible.
        cacheKey = 'actionmenu'
        cached = self._cache.get(cacheKey)
        if cached:
            return cached

        request = self.request
        _ = request.getText
        quotedname = wikiutil.quoteWikinameURL(page.page_name)
        
        menu = [
            'raw',
            'print',
            'refresh',
            'AttachFile',
            'SpellCheck',
            'LikePages',
            'LocalSiteMap',
            'RenamePage',
            'DeletePage',
            ]

        titles = {
            'raw': _('Show Raw Text', formatted=False),
            'print': _('Show Print View', formatted=False),
            'refresh': _('Delete Cache', formatted=False),
            'AttachFile': _('Attach File', formatted=False),
            'SpellCheck': _('Check Spelling', formatted=False), # rename action!
            'RenamePage': _('Rename Page', formatted=False),
            'DeletePage': _('Delete Page', formatted=False),
            'LikePages': _('Show Like Pages', formatted=False),
            'LocalSiteMap': _('Show Local Site Map', formatted=False),
            }

        links = []
        
        # Format standard actions
        available = request.getAvailableActions(page)
        for action in menu:
            # Enable delete cache only if page can use caching
            if action == 'refresh':
                if not page.canUseCache():
                     break
            # Actions which are not available for this wiki, user or page
            if action[0].isupper() and not action in available:
                break;

            link = wikiutil.link_tag(self.request, \
                            quotedname + '?action=' + action, titles[action])
            links.append(link)

        # Add custom actions not in the standard menu
        more = [item for item in available if not item in titles]
        more.sort()
        if more:
            # Add more actions (all enabled)
            for action in more:
                data = {'action': action, 'disabled': ''}
                title = Page(request, action).split_title(request, force=1)
                # Use translated version if available
                title = _(title, formatted=False)
                link = wikiutil.link_tag(self.request, \
                            quotedname + '?action=' + action, title)
                links.append(link)

        html = [
            u'<div class="portlet" id="p-tb">',
            u'<h5>Toolbox</h5>',
            u'<div class="pBody">',
            u'<ul>',
            u'<li>%s</li></ul>' % '</li>\n<li>'.join(links),
            u'</ul>',
            u'</div>',
            u'</div>',
            ]
        html = ''.join(html)
        # cache for next call
        self._cache[cacheKey] = html
        return html


    def username(self, d):
        """ Assemble the username / userprefs link
        Copied from the base class, modified to include hotkeys and link titles
        """
        from MoinMoin.Page import Page
        request = self.request
        _ = request.getText
        
        userlinks = []
        # Add username/homepage link for registered users. We don't care
        # if it exists, the user can create it.
        if request.user.valid:
            homepage = Page(request, request.user.name)
            title = homepage.split_title(request)
            attrs = self.extendedAttrs(_('User Page'), '.')
            homelink = homepage.link_to(request, text=title, attrs=attrs)
            userlinks.append(homelink)
        
            # Set pref page to localized Preferences page
            attrs = self.extendedAttrs(_('My Preferences'), 'u') 
            prefpage = wikiutil.getSysPage(request, 'UserPreferences')
            title = prefpage.split_title(request)
            userlinks.append(prefpage.link_to(request, text=title, attrs=attrs))

            # Add a logout link (not sure this is really necessary
            attrs = self.extendedAttrs(_('log out'), 'o')
            page = d['page']
            url = wikiutil.quoteWikinameURL(page.page_name) + \
                   '?action=userform&logout=1'
            link = wikiutil.link_tag(self.request, url, 'log out', attrs=attrs)
            userlinks.append(link)

        else:
            # Add prefpage links with title: Login
            prefpage = wikiutil.getSysPage(request, 'UserPreferences')
            attrs = self.extendedAttrs('Logging in is not required, but brings benefits', 'o')
            userlinks.append(prefpage.link_to(request, text=_("Login"), attrs=attrs))
            
        html = [
            u'<div class="portlet" id="p-personal">',
            u'<ul id="username">',
            u'<li class="pt-userpage">%s</li></ul>' % '</li>\n<li>'.join(userlinks),
            u'</ul>',
            u'</div>'
            ]
        return ''.join(html)

    def searchform(self, d):
        """ assemble HTML code for the search form
        Tweaks from the bass class to wrap in a 'portlet' class, move the
        description to a header tag, add an access key of 'f' and
        add SearchButton class for the buttons
        """
        _ = self.request.getText
        form = self.request.form
        updates = {
            'search_label' : _('Search:'),
            'search_value': wikiutil.escape(form.get('value', [''])[0], 1),
            'search_full_label' : _('Text', formatted=False),
            'search_title_label' : _('Titles', formatted=False),
            }
        d.update(updates)

        html = u'''
<div class="portlet" id="p-search">
<h5><label for="searchInput">%(search_label)s</label></h5>
<div class="pBody">
<form id="searchform" method="get" action="">
<div>
<input type="hidden" name="action" value="fullsearch">
<input type="hidden" name="context" value="180">
<input id="searchInput" name="value" type="text" accesskey="f"
    value="%(search_value)s">
<input id="titlesearch" name="titlesearch" type="submit" class="searchButton"
    value="%(search_title_label)s" alt="Search Titles">
<input id="fullsearch" name="fullsearch" type="submit" class="searchButton"
    value="%(search_full_label)s" alt="Search Full Text">
</div>
</form>
</div>
</div>
''' % d
        return html

    def shouldShowEditbar(self, page):
        """ Override to include the editbar on edit/preview pages.
        (at the risk that the user may accidentally cancel an edit)
        """
        if (page.exists(includeDeleted=1) and
            self.request.user.may.read(page.page_name)):
            return True        
        return False


    def navibar(self, d):
        """ Alterations from the base class to include access keys and
        descriptions for FrontPage/RecentChanges
        """
        request = self.request
        found = {} # pages we found. prevent duplicates
        links = [] # navibar items
        current = d['page_name']

        # Process config navi_bar
        if request.cfg.navi_bar:
            for text in request.cfg.navi_bar:
                pagename, link = self.splitNavilink(text)
                if pagename == d['page_front_page']:
                    attrs = self.extendedAttrs('Visit the main page', 'z')
                elif pagename == 'RecentChanges':
                    attrs = self.extendedAttrs('List of recent changes in this wiki', 'r')
                else:
                    attrs = ''

                a = wikiutil.link_tag(request, pagename, attrs=attrs)
                links.append(a)         
                found[pagename] = 1

         # Add user links to wiki links, eliminating duplicates.
        userlinks = request.user.getQuickLinks()
        for text in userlinks:
            # Split text without localization, user know what she wants
            pagename, link = self.splitNavilink(text, localize=0)
            if not pagename in found:
                a = wikiutil.link_tag(request, pagename, attrs=attrs)
                links.append(a)                      
                found[pagename] = 1

        html = [
            u'<div class="portlet" id="p-nav">',
            u'<div class="pBody">',
            u'<ul id="navibar">',
            u'<li>%s</li></ul>' % '</li>\n<li>'.join(links),
            u'</ul>',
            u'</div>',
            u'</div>',
            ]
        return ''.join(html)

    def pageinfo(self, page):
        """ Simple override from base class.
        Remove <p> so footer isn't too big
        """
        _ = self.request.getText
        
        if self.shouldShowPageinfo(page):
            info = page.lastEditInfo()
            if info:
                if info['editor']:
                    info = _("last edited %(time)s by %(editor)s") % info
                else:
                    info = _("last modified %(time)s") % info
                return info
        return ''

    def rtl_stylesheet(self, d):
        """ monobook uses a separate css page for rtl alterations.
        Add the rtl stylesheet if the user needs it
        """
        link = ('<link rel="stylesheet" type="text/css" charset="%s"'
                ' media="%s" href="%s">')
        html = []
        if i18n.getDirection(self.request.lang) == 'rtl':
            prefix = self.cfg.url_prefix
            href = '%s/%s/css/%s.css' % (prefix, self.name, 'rtl')
            html.append(link % (self.stylesheetsCharset, 'all', href))
        return '\n'.join(html)

    def html_head(self, d):
        """ Tweak the sending of the head, to include right-to-left 
        alterations if necessary
        """
        html = [
            u'<title>%(title)s - %(sitename)s</title>' % d,
            self.headscript(d), # Should move to separate .js file
            self.html_stylesheets(d),
            self.rtl_stylesheet(d),
            self.rsslink(),
            ]
        return '\n'.join(html)

def execute(request):
    """
    Generate and return a theme object
        
    @param request: the request object
    @rtype: MoinTheme
    @return: Theme object
    """
    return Theme(request)
