# -*- coding: utf-8 mode: python -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8

__all__ = ('defaults', 'Page', 'register', 'next_page',
           'set_trace',
           )

import sys, pdb
from os import path
from Cookie import BaseCookie

from google.appengine.ext.webapp import RequestHandler, template
from django.utils.simplejson.encoder import JSONEncoder

from ulib.base.base import isseq
from ulib.base.uio import _u, _s

def set_trace():
    pdb.Pdb(stdin=sys.__stdin__, stdout=sys.__stdout__).set_trace(sys._getframe().f_back)

_none = []
def defaults(**values):
    def decorator(method):
        def wrapper(*args, **kw):
            self = args[0:1] and args[0] or None
            if self is not None:
                defaults = self.defaults
                if defaults is None: defaults = {}
                defaults.update(values)
                self.defaults = defaults

                for name, default_value in defaults.items():
                    if isseq(default_value):
                        value = self.request.get_all(name)
                        if not value: value = _none
                    else:
                        value = self.request.get(name, _none)
                    if value is not _none:
                        setattr(self, name, value)
            return method(*args, **kw)
        return wrapper
    return decorator

class Page(RequestHandler):
    URL = None
    json = JSONEncoder()

    defaults = None
    def __getattr__(self, name):
        defaults = self.defaults
        if defaults is not None:
            if defaults.has_key(name):
                return defaults[name]
        raise NameError(name)

    def set_cookie(self, key, value='', max_age=None,
                   path='/', domain=None, secure=None, httponly=False,
                   version=None, comment=None):
        cookies = BaseCookie()
        cookies[key] = value
        for var_name, var_value in [
            ('max_age', max_age),
            ('path', path),
            ('domain', domain),
            ('secure', secure),
            ('HttpOnly', httponly),
            ('version', version),
            ('comment', comment),
            ]:
            if var_value is not None and var_value is not False:
                cookies[key][var_name.replace('_', '-')] = str(var_value)
        header_value = cookies[key].output(header='').lstrip()
        self.response.headers.add_header('Set-Cookie', header_value)

    def _render(self, template_name=None, **kw):
        module_name = self.__class__.__module__
        module = sys.modules[module_name]
        if template_name is None:
            template_name = self.__class__.__name__ + '.html'

        defaults = self.defaults
        if defaults is None: values = {}
        else: values = defaults.copy()
        names = values.keys()
        for name in names:
            value = getattr(self, name, _none)
            if value is not _none:
                values[name] = value
        values.update(kw)

        pf = path.join(path.dirname(module.__file__), template_name)
        self.response.out.write(template.render(pf, values))

    def handler(self, *args):
        self._render()

    def get(self, *args):
        self.handler(*args)

    def post(self, *args):
        self.handler(*args)

    def get_error_msg(self):
        u"""Obtenir le message d'erreur de la dernière exception, ainsi que la
        classe CSS associée.

        @return: msg, msgclass
        """
        type, value = sys.exc_info()[:2]
        if type is None:
            return None, u"success"
        elif isinstance(value, Warning):
            return u"%s: %s" % (_u(type.__name__), _u(value)), u"notice"
        elif isinstance(value, Exception):
            return u"%s: %s" % (_u(type.__name__), _u(value)), u"error"

HANDLERS = []
HANDLERS_BY_NAME = {}

def register(handler_cls):
    if handler_cls is None: return None
    if handler_cls.URL is None: return None
    HANDLERS.append((handler_cls.URL, handler_cls))
    HANDLERS_BY_NAME[handler_cls.__name__] = handler_cls
    return handler_cls

def next_page(name, page):
    cls = HANDLERS_BY_NAME.get(name, None)
    if cls is None: raise ValueError("Page not found: %s" % name)
    next_page = cls()
    next_page.initialize(page.request, page.response)
    return next_page
