import threading

from . import custom

# Megaops
def clear():
    model.drop_all()
    model.create_all()

# Transaction-kankei

class TransactionAborted(Exception):
    pass

state = threading.local()

class withness(object):
    def __enter__(self):
        return self
    def __exit__(self,a,b,c):
        if a is None:
            commit_transaction()
        else:
            abort_transaction()

def begin_transaction():
    state.readonly = True
    custom.commit_hooks[0].begin()
    
    return withness()
    
# Raises TransactionAborted if the commit fails
def commit_transaction():
    success = False
    try:
        if not state.readonly:
            for h in custom.commit_hooks[1:]:
                try:
                    h.prepare()
                except Exception,e:
                    raise #TransactionAborted(e)
        # If everyone returned true, try to commit, and if we succeed, go on
        if hasattr(custom.commit_hooks[0],'prepare'):
            try:
                custom.commit_hooks[0].prepare()
            except Exception,e:
                raise #TransactionAborted(e)
        custom.commit_hooks[0].commit()
    except:
        if state.readonly:
            custom.commit_hooks[0].abort()
        else:
            for h in custom.commit_hooks:
                h.abort()
        raise
    else:
        if not state.readonly:
            for h in custom.commit_hooks[1:]:
                h.commit()
    #finally:
    #    model.session.close()
def abort_transaction():
    if state.readonly:
        custom.commit_hooks[0].abort()
    else:
        for h in custom.commit_hooks:
            h.abort()
    #model.session.close()

def __passthrough(name):
    def hookhelper(*args,**kw):
        if state.readonly:
            state.readonly = False
            for h in custom.commit_hooks[1:]:
                h.begin()
        # Do the primary last, because it'll have externally visible effects
        for h in reversed(custom.commit_hooks):
            getattr(h,name)(*args,**kw)
        for h in reversed(custom.commit_hooks):
            if hasattr(h,'post_'+name):
                getattr(h,'post_'+name)(*args,**kw)
    return hookhelper

# Hook passthrough functions
setprop = __passthrough('setprop')
delete = __passthrough('delete')
esetattr = __passthrough('esetattr')
edelete = __passthrough('edelete')
psetattr = __passthrough('psetattr')
pdelete = __passthrough('pdelete')

