from mypyconfig import LOOKUP,FUNC_MODULE_PREFIX_LEN,LOCAL
from types import FunctionType
from byteplay import Code, opmap

from decorator import decorator

from hmako.template import Template
import hmako.lookup


class Render(object): 
    __lookup = hmako.lookup.TemplateLookup(**LOOKUP)
    
    def __init__(self,template=None):
        self.__template = template
        
    def __getattr__(self,name): 
        return None

    def __call__(self,**kwds):
        return self.__lookup.get_template(self.__template).render(G=self,**kwds)


def get_request():
    return LOCAL.request

def _transmute(opcode, arg):
    if (
        (opcode == opmap['LOAD_GLOBAL']) and
        (arg == 'G' or arg == 'request')
    ):
        return opmap['LOAD_FAST'], arg
    return opcode, arg

def render_para_func(func):
    code = Code.from_code(func.func_code)
    code.args = tuple(['request','G'] + list(code.args))
    code.code = [_transmute(op, arg) for op, arg in code.code]
    func.func_code = code.to_code()
    return func


def render_func(func):
    template = "%s/%s.htm"%(
        func.__module__[FUNC_MODULE_PREFIX_LEN:].replace(".", "/"),
        func.__name__
    )
    def  _wrap_func(func,*args, **kwds):
        G=Render(template)
        request = get_request()
        r = func(request,G,*args, **kwds)

        if type(r) is str:
            return r
        elif r is False:
            return ''
        else:
            return G(request=request)

    f = decorator(_wrap_func, func)
    
    func = render_para_func(func)

    return f


def render_doc(func):
    template = Template(
        func.__doc__,
        input_encoding='utf-8',
        output_encoding='utf-8',
        disable_unicode=True,
        default_filters=['str', 'h']
    )

    def _func(func, *args, **kwds):
        request = get_request()
        G=Render()

        r = func(request,G,*args, **kwds)

        if type(r) is str:
            return r
        else:
            return template.render(G=G,request=request)

    f = decorator(_func, func)
    
    func = render_para_func(func)
    
    return f

if __name__ == "__main__":

    @render_doc
    def test():
        """
        my name is ${G.x}
        request is ${request}
        %if G.not_existxxxx:
        xxx
        %else:
            ${G.not_existxxxx}
        %endif
        """
        G.x="zsp<"

    print test()
