"""Program used to generate the logo animation on the pymunk main page.

This program will showcase several features of Pymunk, such as collisions, 
debug drawing, automatic generation of shapes from images, motors, joints and
sleeping bodies.
"""
__docformat__ = "reStructuredText"

import sys
import random
random.seed(5) # try keep difference the random factor the same each run.

import pygame
from pygame.locals import *

import pymunk
from pymunk import Vec2d
import pymunk.pygame_util
import pymunk.autogeometry

fps = 60.0
pygame.init()
screen = pygame.display.set_mode((690, 300))
clock = pygame.time.Clock() 
    
clock.tick(1/5.)

### Physics stuff
space = pymunk.Space()  
space.gravity = 0, 900
space.sleep_time_threshold = 0.3

draw_options = pymunk.pygame_util.DrawOptions(screen)
pymunk.pygame_util.positive_y_is_up = False

### Generate geometry from pymunk logo image
logo_img = pygame.image.load("pymunk_logo_sphinx.png")
logo_bb = pymunk.BB(0,0,logo_img.get_width(), logo_img.get_height())

def sample_func(point):
    try:
        p = pymunk.pygame_util.to_pygame(point, logo_img)
        color = logo_img.get_at(p)
        
        return color.a
        return color.hsla[2]
    except:
        return 0

line_set = pymunk.autogeometry.PolylineSet()
def segment_func(v0, v1):
        line_set.collect_segment(v0, v1)

logo_img.lock()
pymunk.autogeometry.march_soft(
    logo_bb, 
    logo_img.get_width(), logo_img.get_height(), 
    99, 
    segment_func, 
    sample_func)
logo_img.unlock()

r = 10
    
letter_group = 0
for line in line_set:
    line = pymunk.autogeometry.simplify_curves(line, .7)

    max_x = 0
    min_x = 1000
    max_y = 0
    min_y = 1000
    for l in line:
        max_x = max(max_x, l.x)
        min_x = min(min_x, l.x)
        max_y = max(max_y, l.y)
        min_y = min(min_y, l.y)
    w,h = max_x - min_x, max_y - min_y    
        
    # we skip the line which has less than 35 height, since its the "hole" in 
    # the p in pymunk, and we dont need it.
    if h < 35:
        continue

    center = Vec2d(min_x + w/2., min_y + h/2.)   
    t = pymunk.Transform(a=1.0, d=1.0, tx=-center.x, ty=-center.y)

    r += 30
    if r > 255:
        r = 0

    if True:
        for i in range(len(line)-1):
            shape = pymunk.Segment(space.static_body, line[i], line[i+1], 1)
            shape.friction = 0.5
            shape.color = (255,255,255)
            space.add(shape)
    

floor = pymunk.Segment(space.static_body, (-100,300),(1000,220),5)
floor.friction = 1.0
space.add(floor)

### events
def big_ball(space):
    mass = 1000
    radius = 50
    moment = pymunk.moment_for_circle(mass, 0, radius)
    b = pymunk.Body(mass, moment)
    c = pymunk.Circle(b, radius)
    c.friction = 1
    c.color = 255,0,0
    b.position = 800, 100
    b.apply_impulse_at_local_point((-10000,0),(0,-1000))

    space.add(b,c)
    

def boxfloor(space):
    mass = 10
    vs = [(-50,30),(60,22),(-50, 22)]
    
    moment = pymunk.moment_for_poly(mass, vs)
    b = pymunk.Body(mass, moment)
    s = pymunk.Poly(b, vs)
    s.friction = 1
    s.color = 0,0,0
    b.position = 600,50

    space.add(b,s)

box_y = 150
def box(space):
    global box_y
    
    mass = 10
    moment = pymunk.moment_for_box(mass, (40,20))
    b = pymunk.Body(mass, moment)
    s = pymunk.Poly.create_box(b, (40,20))
    s.friction = 1
    b.position = 600,box_y
    box_y -= 30
    space.add(b,s)

def car(space):
    pos = Vec2d(100,200)

    wheel_color = 52,219,119
    shovel_color = 219,119,52
    mass = 100
    radius = 25
    moment = pymunk.moment_for_circle(mass, 20, radius)
    wheel1_b = pymunk.Body(mass, moment)
    wheel1_s = pymunk.Circle(wheel1_b, radius)
    wheel1_s.friction = 1.5
    wheel1_s.color = wheel_color
    space.add(wheel1_b, wheel1_s)

    mass = 100
    radius = 25
    moment = pymunk.moment_for_circle(mass, 20, radius)
    wheel2_b = pymunk.Body(mass, moment)
    wheel2_s = pymunk.Circle(wheel2_b, radius)
    wheel2_s.friction = 1.5
    wheel2_s.color = wheel_color
    space.add(wheel2_b, wheel2_s)

    mass = 100
    size = (50,30)
    moment = pymunk.moment_for_box(mass, size)
    chassi_b = pymunk.Body(mass, moment)
    chassi_s = pymunk.Poly.create_box(chassi_b, size)
    space.add(chassi_b, chassi_s)

    vs = [(0,0),(25,45),(0,45)]
    shovel_s = pymunk.Poly(chassi_b, vs, transform = pymunk.Transform(tx=85))
    shovel_s.friction = 0.5
    shovel_s.color = shovel_color
    space.add(shovel_s)

    wheel1_b.position = pos - (55,0)
    wheel2_b.position = pos + (55,0)
    chassi_b.position = pos + (0,-25)

    space.add(
        pymunk.PinJoint(wheel1_b, chassi_b, (0,0), (-25,-15)),
        pymunk.PinJoint(wheel1_b, chassi_b, (0,0), (-25, 15)),
        pymunk.PinJoint(wheel2_b, chassi_b, (0,0), (25,-15)),
        pymunk.PinJoint(wheel2_b, chassi_b, (0,0), (25, 15))
        )
    
    speed = 4
    space.add(
        pymunk.SimpleMotor(wheel1_b, chassi_b, speed),
        pymunk.SimpleMotor(wheel2_b, chassi_b, speed)
    )
    
def cannon(space):
    mass = 100
    radius = 15
    moment = pymunk.moment_for_circle(mass, 0, radius)
    b = pymunk.Body(mass, moment)
    s = pymunk.Circle(b, radius)
    s.color = 219,52,152
    b.position = 700, -50
    space.add(b,s)
    impulse = Vec2d(-200000,75000)
    b.apply_impulse_at_local_point((impulse))

events = []
events.append((0.1, big_ball))
events.append((2, big_ball))
events.append((3.5, boxfloor))
for x in range(8):
    events.append((4+x*.2, box))
events.append((6.5, car))
events.append((8.5, cannon))

events.sort(key=lambda x:x[0])    

SMALLBALL = pygame.USEREVENT +1
pygame.time.set_timer(SMALLBALL, 100)

small_balls = 100
total_time = 0
while True:
    for event in pygame.event.get():
        if event.type == QUIT or \
            event.type == KEYDOWN and (event.key in [K_ESCAPE, K_q]):  
            sys.exit(0)
        elif event.type == SMALLBALL:
            if small_balls <= 0:
                pygame.time.set_timer(SMALLBALL, 0)
            for x in range(10):
                small_balls -= 1
                mass = 3
                radius = 8
                moment = pymunk.moment_for_circle(mass, 0, radius)
                b = pymunk.Body(mass, moment)
                c = pymunk.Circle(b, radius)
                c.friction = 1
                x = random.randint(100, 400)
                b.position = x,0

                space.add(b,c)

    
    if len(events)>0 and total_time > events[0][0]:
        t, f = events.pop(0)
        
        f(space)
        

    space.step(1./fps)
        
    screen.fill(pygame.color.THECOLORS["white"])
    
    space.debug_draw(draw_options)
    screen.blit(logo_img, (0,0))

    for b in space.bodies:
        p = pymunk.pygame_util.to_pygame(b.position, screen)
    
    pygame.display.flip()

    dt = clock.tick(fps)
    total_time += dt/1000.
 