#-*- coding:utf-8 -*-

#  Copyright © 2009-2017  B. Clausius <barcc@gmx.de>
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <http://www.gnu.org/licenses/>.

DEBUG = False
DEBUG_FUNC = DEBUG_RAND = DEBUG_ROTATE = DEBUG_ERROR = DEBUG_SIM = DEBUG_EMPTY = False
DEBUG_IMPORT = DEBUG_MSGALL = DEBUG_MSG = DEBUG_MSGGL = DEBUG_MSGEXT = DEBUG_CLOCALE = False
DEBUG_DRAW = DEBUG_DRAWNORMALS = DEBUG_DRAWAXES = DEBUG_ALG = DEBUG_KEYS = DEBUG_PICK = DEBUG_MOUSEPOS = False
DEBUG_NOLABEL = DEBUG_NOBLACK = DEBUG_NOBEVEL = DEBUG_NOPICK = DEBUG_INVISIBLE = False
DEBUG_NOCACHE = DEBUG_MODELFAST = DEBUG_CACHEUPDATE = DEBUG_MAXSIZE5 = False
DEBUG_FPS = DEBUG_VFPS = DEBUG_NOCONTROLS = False
DEBUG_SHADER = DEBUG_GLDEBUG = False
DEBUG_PUREPYTHON = DEBUG_INDEXONLY = DEBUG_LIVESHADER = False
DEBUG_LOG = DEBUG_LOGDEBUG = DEBUG_LOGGL = False
DEBUG_QML = DEBUG_LIVEQML = DEBUG_LIVEPLUGINS = False
DEBUG_QSGINFO = DEBUG_BASICRENDERER = False
DEBUG_PHONE = DEBUG_NOLINENO = False

flag_names = sorted(_n for _n in globals().keys() if _n.startswith('DEBUG_'))
__all__ = ['error', 'debug', 'debug_func', 'DEBUG'] + flag_names
flag_nicks = [_n.split('_', 1)[1].lower() for _n in flag_names]

def error(*args, **kwargs):
    print('ERROR:', *args, **kwargs)
    
debug = lambda *args, **kwargs: None
debug_func = lambda x: x

def set_flags(flags):
    from . import debug as module
    module.DEBUG = True
    
    for flag in flags:
        setattr(module, 'DEBUG_' + flag.upper(), True)
        
    if module.DEBUG_MSGALL:
        module.DEBUG_IMPORT = module.DEBUG_MSG = module.DEBUG_MSGGL = True
    if module.DEBUG_IMPORT or module.DEBUG_MSG or module.DEBUG_MSGGL:
        module.DEBUG_MSGEXT = True
    if module.DEBUG_DRAWAXES:
        module.DEBUG_DRAW = True
    if module.DEBUG_DRAWNORMALS:
        module.DEBUG_DRAW = True
    if module.DEBUG_LOGDEBUG or module.DEBUG_LOGGL:
        module.DEBUG_LOG = True
    if module.DEBUG_LOG:
        import logging
        logging.basicConfig(filename='pybik.log',
                            level=logging.DEBUG if module.DEBUG_LOGDEBUG else logging.INFO)
    if module.DEBUG_VFPS:
        module.DEBUG_FPS = True
    
    if module.DEBUG_FUNC:
        def _debug_pre_func(func, *args, **kwargs):
            def short_arg(arg):
                arg = str(arg)
                maxlen = 80 - debug_func.indent * 3 - 2
                if len(arg) > maxlen:
                    return arg[:maxlen]
                return arg
            func_name = ' '.join(reversed(func.__qualname__.split('.')))
            print('%s--%s ' % ('  |'*debug_func.indent, func_name))
            debug_func.indent += 1
            for arg in args:
                try:
                    print('%s: %s' % ('  |'*debug_func.indent, short_arg(arg)))
                except Exception:
                    pass
            for kw, arg in kwargs.items():
                try:
                    print('%s: %s=%s' % ('  |'*debug_func.indent, kw, short_arg(arg)))
                except Exception:
                    pass
        def debug_func(func):
            def ret_func(*args, **kwargs):
                _debug_pre_func(func, *args, **kwargs)
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    if debug_func.last_exc != e:
                        print('  X'*debug_func.indent)
                        debug_func.last_exc = e
                    raise
                finally:
                    debug_func.indent -= 1
                    print('  |'*debug_func.indent + "--'")
            try:
                ret_func.__dict__ = func.__dict__
            except AttributeError:
                pass
            ret_func.__doc__ = func.__doc__
            ret_func.__module__ = func.__module__
            ret_func.__name__ = func.__name__
            try:
                ret_func.__defaults__ = func.__defaults__
            except AttributeError:
                pass
            return ret_func
        debug_func.indent = 0
        debug_func.last_exc = None
        module.debug_func = debug_func
        def meta(*bases):
            meta = type(bases[0]) if bases else type
            class _CooperativeMeta (meta):
                def __new__(cls, name, bases, namespace):
                    import types
                    print('functions in %s:' % namespace['__qualname__'])
                    for k, v in sorted(namespace.items()):
                        if type(v) is types.FunctionType:
                            print(' ', k)
                            namespace[k] = debug_func(v)
                    return meta(name, bases, namespace)
                def __init__(self, name, bases, namespace):
                    meta.__init__(self, name, bases, namespace)
            return _CooperativeMeta
        module.meta = meta
        
    if module.DEBUG_MSG:
        module.debug = print
        
def set_flagstring(value):
    if not DEBUG:
        from . import config
        print(config.APPNAME, config.VERSION)
    flags = [f for f in value.split(',') if f]
    print('debug flags:', *flags, flush=True)
    for f in flags:
        if f not in flag_nicks:
            print('unknown flag:', f)
            raise SystemExit(1)
    set_flags(flags)
    

