import os, sys
sys.path.append(os.path.abspath('../tool'))

import math

import defensive

log = defensive.Logging()

@log.debug
def ontheirfeetBehavior(bubble,context):
    inbubble = context
    if 'gravity' in context.tag:
        dx,dy = bubble.getDelta(inbubble)
        dist = bubble.getDistSQ(inbubble)**0.5
        bubble = bubble.setDirection(dx/dist,dy/dist)
    return bubble

@log.debug
def movableBehavior(bubble, context):
    """
    bubbleWill = bubble.giggle()
    inbubble = context.recursiveCollisionDetection(bubbleWill)
    if 'solid' in inbubble.tag:
        dx,dy = inbubble.getDelta(bubble)
        dist = inbubble.getDistSQ(bubble)**0.5
        return bubble.stop()#.push(-0.2*dx/dist,-0.2*dy/dist)
    return bubbleWill
    """
    return bubble

@log.debug
def fallingBehavior(bubble,context):
    constant = 0.006
    inbubble = context
    if 'gravity' in inbubble.tag:
        deltaX,deltaY = bubble.getDelta(inbubble)
        dist = bubble.getDistSQ(inbubble)**0.5
        return bubble.push(-constant*deltaX/dist,-constant*deltaY/dist)
    return bubble

@log.debug
def springBehavior(length,force,forceLink):
    def closure(bubble,context):
        fx,fy = 0,0
        newLink = []
        for link in bubble.link:
            dx,dy = bubble.getDelta(link)
            dist = math.hypot(dx,dy)
            vx = dx/dist if dist !=0 else dx
            vy = dy/dist if dist !=0 else dy
            diff = (length-abs(dist))
            fx += force*diff*vx
            fy += force*diff*vy
            newLink.append(link.push(-forceLink*diff*vx,-forceLink*diff*vy))
        return bubble.push(fx,fy).updateLink(newLink)
    return closure

@log.debug
def destroyableBehavior(bubble,context):
    link = list(bubble.link)
    if 'bullet' in context.tag:
        x,y = context.x,context.y
        explosion = Bubble('hole',\
                            (context.x,context.y),\
                            10,\
                            (0,-1),\
                            (0,0),\
                            [],\
                            [],\
                            AinsideB,\
                            [explodingBehavior],\
                            ['explosion']).translate(x,y)
        link.append(explosion)
    return bubble.updateLink(link)

@log.debug
def explodingBehavior(bubble,context):
    if not 'bullet' in context.tag:
        return bubble.removeTag('explosion')
    return bubble
    
@log.debug
def bulletBehavior(bubble,context):
    if 'explosion' in context.tag:
        return bubble.addTag('vanish')
    return bubble

@log.debug
def vanishableLinkBehavior(bubble,context):
    newLnks = []
    for link in bubble.link:
        if not 'vanish' in link.tag:
            newLnks.append(link)
    return bubble.updateLink(newLnks)

suite = {
    'movableBehavior':[movableBehavior],
    'fallingBehavior':[fallingBehavior],
    'springBehavior':[springBehavior(20,0.02,0.08)],
    'ontheirfeetBehavior':[ontheirfeetBehavior],
    
    'destroyableBehavior':[destroyableBehavior],
    'explodingBehavior':[explodingBehavior],
    'bulletBehavior':[bulletBehavior],
    
    'vanishableLinkBehavior':[vanishableLinkBehavior]
}
