# coding=cp1251

cacheable = (u'раб.бюджет2005.списоксправ',
           u'accuracy'
           )

import core
import krok
try:
    import dile
except ImportError:
    dile = None


class caller(object):
    def __init__(self, cb):
        self.cb = cb
        self.cache = {}

    def execute(self, f_name, f_args=[], func_typ=None):
        global cacheable
        if not isinstance(f_name, unicode):
            f_name = f_name.decode("1251")
        func = None
        if f_name in core.aliases:
            if '.' in core.aliases[f_name]:
                func = eval("core." + core.aliases[f_name])
            else:
                func = core.__dict__[core.aliases[f_name]]
        elif f_name in krok.aliases:
            func = krok.__dict__[krok.aliases[f_name]]
        elif dile is not None and f_name.lower() in dile.aliases:
            func = dile.aliases[f_name.lower()]

        if func is not None:
            args_ = [arg.decode('1251') if isinstance(arg, str) else arg \
                          for arg in f_args]
            #self.cb.execute('Trace', (repr(args_),), None)
            res = func(*args_)
            #self.cb.execute('Trace', (repr(res),), None)
            return res

        if f_name.lower() in cacheable:
            key = (f_name.lower(), tuple(f_args), func_typ)
            if key in self.cache:
                return self.cache[key]

        res = self.cb.execute(f_name.encode("1251"), f_args, func_typ)

        if f_name.lower() in cacheable:
            self.cache[key] = res
        return res

    def __getattr__(self, name):
        '''Allow support for None-result function without 'execute' method

        This could be procedures or functions which ignore 'func_typ' param
        (designed for python-callback or wrappers for TB6.9 builtin)
        '''
        def my_func(*args):
            self.execute(name, args, None)

        return my_func
