# -*- coding: iso-8859-1 -*-
"""MoinMoin theme "sinorca4moin" by David Linke.

See MoinMoin:DavidLinke/Sinorca4Moin for more infos.

Version 0.5b   : changing css a bit (also made css2.1. compatible) and 
                 updating the theme for MoinMoin Version 1.8 
                 Attention: this is not an official release, more a
                 personal update (Marcel Haefner)!
Version 0.5    : Version adjusted for moin-1.6.x (2007-12-29)
Version 0.4    : Extended version adjusted for moin-1.5.x (2006-08-13)
Version 0.1-0.3: Initial version for moin-1.3.x (2005)

Inspired by Haran's sinorca-design published at www.oswd.org.

$Id: sinorca4moin.py 159 2007-12-29 21:43:07Z linke $
"""

import os
from MoinMoin.theme import ThemeBase
from MoinMoin.Page import Page
from MoinMoin.config.multiconfig import _url_re_list, _makeConfig, _getConfigName
from MoinMoin import wikiutil, error

class Theme(ThemeBase):

    name = "sinorca4moin"

    def farmWikiList(self):
        """Generate list of links pointing to the wikis of the farm

        Fore each Subwiki a link to Frontpage and RecentChanges (image) is
        created. If interwiki_preferred is specified in the farmconfig the
        links will be created only for these wikis else links to all wikis
        in farmconfig.wiki will be created.
        """
        _ = self.request.getText
        farmwikis =  [wiki_name for wiki_name, reg in _url_re_list()]
        if self.request.cfg.interwiki_preferred:
            wikis = self.request.cfg.interwiki_preferred
            # remove everything that is not a wiki of the farm
            wikis = [w for w in wikis if w in farmwikis]
        else:
            wikis = farmwikis

        if len(wikis) < 2: return []  # creating links is useless for one wiki

        linkList = []
        for wiki_name in wikis:
            cfg = _makeConfig(wiki_name)
            highlight = u''
            if wiki_name == _getConfigName(self.request.url):
                highlight = u' class="highlight"'
            try:
                interwiki_list = wikiutil.load_wikimap(self.request)
                wiki_url = interwiki_list[cfg.interwikiname]
                rc = _("RecentChanges", formatted=False)
                linkList.append( ''.join([
                    u' <a title="%s" href="%s"%s>%s</a>' %
                        (cfg.sitename, wiki_url, highlight, cfg.interwikiname),
                    u'<a title="%s" href="%s%s">' %
                        (rc, wiki_url, wikiutil.quoteWikinameURL(rc)),
                    u'<img src="%s/sinorca4moin/img/moin-diff.png" alt="%s"' %
                            (cfg.url_prefix_static, rc),
                    u' height="11" width="15"></a>'
                    ]))
            except KeyError: # probably no interwikiname in config
                msg = """
Missing the wiki '%s' in the interwiki list.

Please add the interwiki-name and the url of this wiki to 'intermap.txt'.
"""%wiki_name
                #raise error.ConfigurationError(msg)
                pass
        return linkList

    def subheader(self):
        """Make subheader

        Links to subwikis if it's a farm else uses page_header2.
        """
        linkList = self.farmWikiList()
        if len(linkList) > 1:
            subheader = ' |\n'.join(linkList)
        else:
            subheader = self.request.cfg.page_header2
        return '\n'.join([
            u'<div class="subHeader">',
            subheader,
            u'</div>',
            ])

    def title(self, d):
        """ Assemble the title (not as html list as in standard method!)

        Code copied from title-method in __init__.py
        Only one line was changed.

        @param d: parameter dictionary
        @rtype: string
        @return: title html
        """
        _ = self.request.getText
        content = []
        if d['title_text'] == d['page'].split_title(): # just showing a page,
            curpage = ''                               # no action
            segments = d['page_name'].split('/') # was: title_text
            for s in segments[:-1]:
                curpage += s
                # next line is modified compared to method in _init__.py
                content.append("%s&nbsp;/ " % Page(self.request,
                    curpage).link_to(self.request, s))
                curpage += '/'
            link_text = segments[-1]
            link_title = _('Click to do a full-text search for this title',
                           formatted=False)
            link_query = {
                'action': 'fullsearch',
                'value': 'linkto:"%s"' % d['page_name'],
                'context': '180',
            }
            # we dont use d['title_link'] any more, but make it ourselves:
            link = d['page'].link_to(self.request, link_text,
                                     querystr=link_query,
                                     title=link_title, css_class='backlink',
                                     rel='nofollow')
            content.append(('<li>%s</li>') % link)
        else:
            content.append('<li>%s</li>' % wikiutil.escape(d['title_text']))

        html = '''
<ul id="pagelocation">
%s
</ul>
''' % "".join(content)
        return html

    def iconbar(self, d):
        """
        Assemble the iconbar
        
        @param d: parameter dictionary
        @rtype: string
        @return: iconbar html
        """
        iconbar = []
        if self.cfg.page_iconbar and self.request.user.show_toolbar and d['page_name']:
            iconbar.append('<ul id="iconbar">\n')
            icons = self.cfg.page_iconbar[:]
            for icon in icons:
                if icon == "up":
                    if d['page_parent_page']:
                        iconbar.append('<li>%s</li>\n' % self.make_iconlink(icon, d))
                elif icon == "subscribe" and self.cfg.mail_enabled:
                    iconbar.append('<li>%s</li>\n' % self.make_iconlink(
                        ["subscribe", "unsubscribe"][self.request.user.isSubscribedTo([d['page_name']])], d))
                else:
                    iconbar.append('<li>%s</li>\n' % self.make_iconlink(icon, d))
            iconbar.append('</ul>\n')
        return ''.join(iconbar)

    def wikipanel(self, d):
        """ Create wiki panel """
        _ = self.request.getText
        html = [
            u'<div class="sidepanel">',
            u'<h1>%s</h1>' % _("Wiki"),
            self.navibar(d),
            u'</div>',
            ]
        return u'\n'.join(html)

    def pagepanel(self, d):
        """ Create page panel """
        _ = self.request.getText
        if self.shouldShowEditbar(d['page']):
            html = [
                u'<div class="sidepanel">',
                u'<h1>%s</h1>' % _("Page"),
                self.editbar(d),
                u'</div>',
                ]
            return u'\n'.join(html)
        return ''

    def userpanel(self, d):
        """ Create user panel """
        _ = self.request.getText

        html = [
            u'<div class="sidepanel">',
            u'<h1>%s</h1>' %  _("User"),
            self.username(d),
            u'</div>'
            ]
        return u'\n'.join(html)

    def linkedSitename(self):
        """Create title from sitename and link to FrontPage"""
        frontpage = wikiutil.getFrontPage(self.request).page_name
        html = wikiutil.link_tag(self.request,
                                 wikiutil.quoteWikinameURL(frontpage),
                                 self.request.cfg.sitename)
        return html

    def flexible_userhome(self, d):
        """Determine content in superheader and sidebar based on page_header1
        """
        if self.cfg.page_header1:
            superheader = self.cfg.page_header1
            userpanel = self.userpanel(d)
        else:
            #superheader = self.username(d)
            superheader = '\n'.join([
                u'  <div class="right">',
                self.username(d),
                u'  </div>',
                ])
            userpanel = ''
        return superheader, userpanel

    def shortenPagename(self, name):
        """ Shorten page names (overrides default method)

        changed compared to default: for hierarchical names a part of
        the first level is always shown.

        @param name: page name, unicode
        @rtype: unicode
        @return: shortened version of page name
        """
        l1Length = 8   # length to which level1 of page name will be truncated
        maxLength = self.maxPagenameLength()
        if len(name) > maxLength:
            half, left = divmod(maxLength, 2)
            name = name.split('/')
            parts = len(name)
            # select separator based on number of levels
            if parts > 2:
                nameStart, nameEnd = name[0], name[-1]
                if (len(nameStart) + len(nameEnd) > maxLength-4
                    and len(nameStart) > l1Length):
                    # cut from start
                    if len(nameEnd) > maxLength-6-l1Length:
                        name = u'%s../../%s..' % (nameStart[:l1Length],
                                nameEnd[:maxLength-8-l1Length])
                    else:
                        lenStart = max(maxLength-len(nameEnd)-6, l1Length)
                        name = u'%s../../%s' % (nameStart[:lenStart],
                                nameEnd[:maxLength-6-lenStart])
                elif len(nameStart) + len(nameEnd) > maxLength-4:
                    # cut form end only
                    name = u'%s/../%s..' % (nameStart,
                            nameEnd[:maxLength-6-len(nameStart)])
                else:
                    name = u'%s/../%s' % (nameStart, nameEnd)
            elif parts == 2:
                nameStart, nameEnd = name[0], name[-1]
                if (len(nameStart) + len(nameEnd) > maxLength-1
                    and len(nameStart) > l1Length):
                    # cut from start
                    if len(nameEnd) > maxLength-3-l1Length:
                        name = u'%s../%s..' % (nameStart[:l1Length],
                                nameEnd[:maxLength-5-l1Length])
                    else:
                        lenStart = max(maxLength-len(nameEnd)-3, l1Length)
                        name = u'%s../%s' % (nameStart[:lenStart],
                                nameEnd[:maxLength-3-lenStart])
                elif len(nameStart) + len(nameEnd) > maxLength-1:
                    # cut from end only
                    name = u'%s/%s..' % (nameStart,
                            nameEnd[:maxLength-3-len(nameStart)])
                else:
                    name = u'%s/%s' % (nameStart, nameEnd)
            else:
                # simply replace middle with '...' for long pagenames
                half, left = divmod(maxLength-3, 2)
                name = name[0]
                name = u'%s...%s' % (name[:half + left], name[-half:])
        return name

    def header(self, d):
        """
        Assemble page header

        @param d: parameter dictionary
        @rtype: string
        @return: page header html
        """
        _ = self.request.getText

        superheader, userpanel = self.flexible_userhome(d)

        html = [
            # Header
            u'<div id="header">',

            # super-header
            u' <div class="superHeader">',
            superheader,
            u' </div>',
            self.searchform(d),

            # middle header
            u' <div class="midHeader">',
            u'  <div id="locationline">',
            self.logo(),
            #self.interwiki(d), # makes no sense in this theme
            self.linkedSitename(),
            u'  </div>',
            u' </div>',

            # we display all wikis of the farm as links in one line
            self.emit_custom_html(self.subheader()),

            # Custom html below header (not recomended!)
            #self.emit_custom_html(self.cfg.page_header2),

            self.trail(d),
            u'</div>',

            # Sidebar
            u'<div id="sidebar">',
            self.wikipanel(d),
            self.pagepanel(d),
            userpanel,
            u'</div>',

            self.msg(d),

            # Page
            self.startPage(),

            # Iconbar
            self.iconbar(d),

            self.title(d),
            ]
        return u'\n'.join(html)

    def editorheader(self, d):
        """
        Assemble page header for editor

        @param d: parameter dictionary
        @rtype: unicode
        @return: page header html
        """
        _ = self.request.getText
        superheader, userpanel = self.flexible_userhome(d)

        html = [
            # Header
            u'<div id="header">',

            # super-header
            u' <div class="superHeader">',
            superheader,
            u' </div>',

            # middle header
            u' <div class="midHeader">',
            self.searchform(d),
            u'  <div id="locationline">',
            self.logo(),
            #self.interwiki(d), # makes no sense in this theme
            self.linkedSitename(),
            u'  </div>',
            u' </div>',

            # we display all wikis of the farm as links in one line
            self.emit_custom_html(self.subheader()),
            u'</div>',

            # Sidebar
            u'<div id="sidebar">',
            self.wikipanel(d),
            self.pagepanel(d),
            userpanel,
            u'</div>',

            self.msg(d),

            # Page
            self.startPage(),
            ]
        return u'\n'.join(html)

    def footer(self, d, **keywords):
        """ Assemble page footer

        @param d: parameter dictionary
        @keyword ...:...
        @rtype: unicode
        @return: page footer html
        """
        page = d['page']
        html = [
            # End of page
#?            # Used to extend the page to the bottom of the sidebar
#?            u'<div id="pagebottom"></div>',
            self.pageinfo(page),
            self.endPage(),

            # Pre footer custom html (not recommended!)
            #self.emit_custom_html(self.cfg.page_footer1),

            # Footer
            u'<div id="footer">',
            self.credits(d),
            self.showversion(d, **keywords),
            u'</div>',

            # Post footer custom html
            #self.emit_custom_html(self.cfg.page_footer2),
            ]
        return u'\n'.join(html)

    def splitNavilink_off(self, text, localize=1):
        """ Split navibar links into pagename, link to page

        This overrides the defaut method. In contrast to default quicklinks
        are cut down to a maximum length

        @param text: the text used in config or user preferences
        @rtype: tuple
        @return: pagename or url, link to page or url
        """
        request = self.request

        # Handle [pagename title] or [url title] formats
        if text.startswith('[') and text.endswith(']'):
            try:
                pagename, title = text[1:-1].strip().split(' ', 1)
                title = title.strip()
                localize = 0
            except (ValueError, TypeError):
                # Just use the text as is.
                pagename = title = text

        # Handle regular pagename like "FrontPage"
        else:
            # Use localized pages for the current user
            if localize:
                page = wikiutil.getLocalizedPage(request, text)
            else:
                page = Page(request, text)
            pagename = page.page_name
            title = page.split_title(request)
            title = self.shortenPagename(title)
            link = page.link_to(request, title)


        from MoinMoin import config
        for scheme in self.linkSchemas:
            if pagename.startswith(scheme):
                title = self.shortenPagename(wikiutil.escape(title))  # DL change
                link = '<a href="%s">%s</a>' % (pagename, title)
                return pagename, link

        # remove wiki: url prefix
        if pagename.startswith("wiki:"):
            pagename = pagename[5:]

        # try handling interwiki links
        try:
            interwiki, page = pagename.split(':', 1)
            thiswiki = request.cfg.interwikiname
            if interwiki == thiswiki:
                pagename = page
                title = self.shortenPagename(page)  # DL change
            else:
                return (pagename,
                        self.request.formatter.interwikilink(True, interwiki, page) +
                        page +
                        self.request.formatter.interwikilink(False, interwiki, page)
                        )

        except ValueError:
            pass

        # Normalize page names, replace '_' with ' '. Usually
        # all names use spaces internally, but for
        # [name_with_spaces label] we must save the underscores
        # until this point.
        pagename = request.normalizePagename(pagename)
        link = Page(request, pagename).link_to(request, title)

        return pagename, link

def execute(request):
    """ Generate and return a theme object

    @param request: the request object
    @rtype: MoinTheme
    @return: Theme object
    """
    return Theme(request)

