#!/usr/bin/python
# -*- coding: UTF-8 -*-

"""
    {% lucidTag ... %}
    ~~~~~~~~~~~~~~~~~~

    the special PyLucid tag who starts a plugin with the plugin manager.
    e.g.: {% lucidTag plugin_name.method_name key1="value1" key2="value2" %}

    registered in: ./PyLucid/defaulttags/__init__.py

    Last commit info:
    ~~~~~~~~~~~~~~~~~
    $LastChangedDate: 2008-01-03 16:07:03 +0100 (Do, 03 Jan 2008) $
    $Rev: 1365 $
    $Author: JensDiemer $

    :copyright: 2007 by Jens Diemer
    :license: GNU GPL v3, see LICENSE.txt for more details.
"""

import cgi, re

from PyLucid.system.plugin_manager import run
from PyLucid.system.response import SimpleStringIO
from PyLucid.system.context_processors import add_css_tag

from django.conf import settings
from django import template


# FIXME: The re should be more fault-tolerant:
KWARGS_REGEX = re.compile('''(\w*?)\=['"](.*?)['"]''')

# Not all plugin output should surrounded with a <div> tag:
CSS_TAG_BLACKLIST = ("page_style", "RSSfeedGenerator",)


class lucidTagNodeError(template.Node):
    """
    display a error messages in the cms page for a wrong lucidTag.
    """
    def __init__(self, plugin_name, method_name, msg):
        self.plugin_name = plugin_name
        self.method_name = method_name
        self.msg = msg

    def render(self, context):
        txt = "[lucidTag %s.%s syntax error: %s]" % (
            self.plugin_name, self.method_name, self.msg
        )
        return txt


class lucidTagNode(template.Node):
    def __init__(self, plugin_name, method_name, method_kwargs):
        self.plugin_name = plugin_name
        self.method_name = method_name
        self.method_kwargs = method_kwargs

    def __repr__(self):
        return "<lucidTag node ('%s.%s' kwargs:%s)>" % (
            self.plugin_name, self.method_name, self.method_kwargs
        )

    def render(self, context):
        local_response = SimpleStringIO()
        output = run(
            context, local_response,
            self.plugin_name, self.method_name,
            method_kwargs = self.method_kwargs
        )
        if output == None:
            content = local_response.getvalue()
        elif isinstance(output, basestring):
            content = output
        else:
            msg = (
                "Error: Wrong output from inline Plugin!"
                " - It should be write into the response object and return None"
                " or return a basestring!"
                " - But %s.%s has returned: %s (%s)"
            ) % (
                self.plugin_name, self.method_name,
                repr(output), type(output)
            )
            raise AssertionError(msg)

        if not self.plugin_name in CSS_TAG_BLACKLIST:
            content = add_css_tag(
                context, content, self.plugin_name, self.method_name
            )

        return content


def lucidTag(parser, token):
    """
    Parse the lucidTags.

    syntax e.g.:
        {% lucidTag PluginName %}
        {% lucidTag PluginName kwarg1="value1" %}
        {% lucidTag PluginName kwarg1="value1" kwarg2="value2" %}
    """
    content = token.contents
    content = content.split(" ", 2)[1:]
    plugin_name = content.pop(0)

    method_kwargs = {}
    if content:
        kwargs = content[0]
        kwargs = KWARGS_REGEX.findall(kwargs)
        for key, value in kwargs:
            # method Keywords must be Strings
            key = key.encode(settings.DEFAULT_CHARSET)
            if value in ("True", "true", "on", "ON", "1"):
                value = True
            elif value in ("False", "false", "off", "OFF", "0"):
                value = False
            method_kwargs[key] = value

    if "." in plugin_name:
        plugin_name, method_name = plugin_name.split(".", 1)
    else:
        method_name = "lucidTag"

    return lucidTagNode(plugin_name, method_name, method_kwargs)

