#
# SchoolTool - common information systems platform for school administration
# Copyright (c) 2005 Shuttleworth Foundation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
"""
Student Intervention browser report views.
"""
import cgi
import re
import random

from reportlab.platypus import Paragraph
from zope.component import queryMultiAdapter
from zope.viewlet.interfaces import IViewletManager
from zope.component.interfaces import ComponentLookupError
from zope.viewlet.viewlet import CSSViewlet, JavaScriptViewlet


ReportsCSSViewlet = CSSViewlet("reportsViewlet.css")
ReportsJSViewlet = JavaScriptViewlet("reportsViewlet.js")


def _para(text, style):
    """Helper which builds a reportlab Paragraph flowable"""
    if text is None:
        text = ''
    elif isinstance(text, unicode):
        text = text.encode('utf-8')
    else:
        text = str(text)
    return Paragraph(cgi.escape(text), style)


def _unescape_FCKEditor_HTML(text):
    text = text.replace(u'&amp;', u'&')
    text = text.replace(u'&lt;', u'<')
    text = text.replace(u'&gt;', u'>')
    text = text.replace(u'&quot;', u'"')
    text = text.replace(u'&#39;', u"'")
    text = text.replace(u'&rsquo;', u"'")
    text = text.replace(u'&nbsp;', u' ')
    return text


escaped_reportlab_tags_re = re.compile(
    r'&lt;(/?((strong)|(b)|(em)|(i)))&gt;')

html_p_tag_re = re.compile(r'</?p[^>]*>')
html_br_tag_re = re.compile(r'</?br[^>]*>')


def buildHTMLParagraphs(snippet):
    """Build a list of paragraphs from an HTML snippet."""
    if not snippet:
        return []
    paragraphs = []
    tokens = []
    for token in html_p_tag_re.split(snippet):
        if not token or token.isspace():
            continue
        tokens.extend(html_br_tag_re.split(token))
    for token in tokens:
        if not token or token.isspace():
            continue
        # Reportlab is very sensitive to unknown tags and escaped symbols.
        # In case of invalid HTML, ensure correct escaping.
        fixed_escaping = cgi.escape(_unescape_FCKEditor_HTML(unicode(token)))
        # Unescape some of the tags which are also valid in Reportlab
        valid_text = escaped_reportlab_tags_re.sub(u'<\g<1>>', fixed_escaping)
        paragraphs.append(valid_text)
    return paragraphs


class IReportsViewletManager(IViewletManager):
    """Provides a viewlet hook for report items."""


class ReportsViewlet(object):
    """Schooltool action acting as drop-down menu item.

    Sub-items are collected from specified viewlet manager.
    """

    manager_interface = IReportsViewletManager
    manager_name = "schooltool.intervention.reports_action_manager"

    viewlet_manager = None

    _tag_uid = None

    @property
    def tag_uid(self):
        if self._tag_uid is None:
            self._tag_uid = u'MENU_'
            for i in range(15):
                self._tag_uid += unichr(ord(u'a') + random.randint(0, 25))
        return self._tag_uid

    def update(self):
        try:
            self.viewlet_manager = queryMultiAdapter(
                (self.context, self.request, self),
                self.manager_interface,
                name=self.manager_name)
            # Update __parent__ of the manager, so that it's viewlets could
            # be registered for the actual view instead of this viewlet.
            self.viewlet_manager.__parent__ = self.__parent__
        except ComponentLookupError:
            pass

        if self.viewlet_manager is not None:
            self.viewlet_manager.update()

    def render(self, *args, **kw):
        if (self.viewlet_manager is None or
            not self.viewlet_manager.viewlets):
            return ''
        return self.index(*args, **kw)

