from django.conf import settings
if not (getattr(settings,'LOG_ROOT','') and getattr(settings,'APPNAME','')):
    def logview(func):
        return func
    logviewmethod = logview
else:
    import os, time, traceback, StringIO
    def getLogFN(request):
        fn = os.path.join(settings.LOG_ROOT, '%s-%s-%s-log.txt' % (request.META.get('SERVER_NAME'), settings.APPNAME, time.strftime('%Y%m%d',time.gmtime())))
        dn = os.path.dirname(fn)
        if not os.path.isdir(dn):
            os.makedirs(dn)
        return fn

    def makeValue(v):
        if isinstance(v,(basestring,tuple,list,bool,float,int)):
            if isinstance(v,(bool,float,int)):
                return str(v)
            elif isinstance(v,basestring):
                if isinstance(v,unicode): v = v.encode('utf8')
                return repr(v)
            else:
                R = [makeValue(e) for e in v]
                if None in R or [e for e in R if not isinstance(e,str)]:
                    return None
                return ','.join(R)

    def makeRecord(KV):
        '''map Key Value dict to a record'''
        R = [time.strftime('[%d/%b/%Y:%H:%M:%S +0000]',time.gmtime())]
        aR = R.append
        for k in sorted(KV.keys()):
            v = makeValue(KV[k])
            if v is not None:
                aR('%s=%s' % (k,v))
        return ('\t'.join(R))+'\n'

    def logview(func):
        "This decorator logs a view type function"
        argnames = func.func_code.co_varnames[:func.func_code.co_argcount]
        fname = func.func_name
        def logging_func(*args,**kwds):
            request = args[0]
            KV = {}
            META = request.META
            if 'wsgi.url_scheme' in META:
                KV['URL_SCHEME'] = META['wsgi.url_scheme']
            KV.update(kwds)
            KV.update(zip(argnames[1:],args[1:]))
            method = request.method
            try:
                user = getattr(request,'user',None)
            except:
                user = None

            if user:
                username = user.username
            else:
                username = '[UNKNOWN]'
            KV['USERNAME'] = username

            KV['VIEWFUNC'] = fname
            KV['APPLICATION'] = settings.APPNAME
            KV.update([(k,v) for k,v in META.iteritems() if not k.startswith('wsgi.')])
            for D in method=='POST' and (request.GET,request.POST) or (request.GET,):
                for k,v in D.iterlists():
                    if len(v)==1:
                        KV[k] = v[0]
                    else:
                        KV[k] = v   #special case multiple values
            if 'REQUEST_METHOD' not in KV:
                KV['REQUEST_METHOD'] = method
            logFN = getLogFN(request)
            try:
                try:
                    request._logging_dict = KV
                    return func(*args, **kwds)
                except:
                    s = StringIO.StringIO()
                    traceback.print_exc(file=s)
                    KV['ERROR'] = s.getvalue()
                    raise
            finally:
                try:
                    #safe attempt at writing the log
                    f = open(logFN,'a')
                    f.write(makeRecord(KV))
                    f.close()
                except:
                    if settings.DEBUG:
                        raise
        return logging_func

    def on_method(function_decorator):
        def decorate_method(unbound_method):
            def method_proxy(self, *args, **kwargs):
                def f(*a, **kw):
                    return unbound_method(self, *a, **kw)
                f.func_name = self.__class__.__name__
                return function_decorator(f)(*args, **kwargs)
            return method_proxy
        return decorate_method

    logviewmethod = on_method(logview)
