#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright 2010 British Broadcasting Corporation and Kamaelia Contributors(1)
# (1) Kamaelia Contributors are listed in the AUTHORS file and at
#     http://www.kamaelia.org/AUTHORS - please extend this file,
#     not this notice.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#     http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# See the License for the specific language governing permissions and
# limitations under the License.
# -------------------------------------------------------------------------
# first test of Physics module
import Kamaelia.Support.Particles
import Kamaelia.UI.MH
import pygame
from pygame.locals import *
from random import randrange
import random
from Axon.Component import component
# class component(object): pass
class VisibleParticle(Kamaelia.Support.Particles.Particle):
    """Version of Kamaelia.Support.Particles.Particle with added rendering functions,
    and a list of particles it is bonded to."""
    def __init__(self, position, pname, radius):
        super(VisibleParticle,self).__init__(position=position, ID=pname )
        self.radius = radius
        font = pygame.font.Font(None, 24)
        self.label = font.render(self.ID, False, (0,0,0))
    def renderBonds(self, surface):
        """Renders lines representing the bonds going from this particle"""
        for p in self.bondedTo:
            pygame.draw.line(surface, (128,128,255), [int(i) for i in self.pos],  [int(i) for i in p.pos])
    def renderSelf(self, surface):
        """Renders a circle with the particle name in it"""
        pygame.draw.circle(surface, (255,128,128), (int(self.pos[0]), int(self.pos[1])), self.radius)
        surface.blit(self.label, (int(self.pos[0]) - self.label.get_width()/2, int(self.pos[1]) - self.label.get_height()/2))
class ParticleDragger(Kamaelia.UI.MH.DragHandler):
     def detect(self, pos, button):
         inRange = self.app.physics.withinRadius( pos, self.app.particleRadius )
         if len(inRange) > 0:
             self.particle = inRange[0][0]
             return self.particle.getLoc()
             return False
     def drag(self,newx,newy):
         self.particle.pos = (newx,newy)
     def release(self,newx, newy):
         self.drag(newx, newy)
class PhysApp1(Kamaelia.UI.MH.PyGameApp, component):
    """Simple physics demonstrator app"""
    def __init__(self, screensize, fullscreen = False, nodes = None, initialTopology=[], border=100):
        super(PhysApp1, self).__init__(screensize, "Physics test 1, drag nodes to move them", fullscreen)
        self.border = border
        self.initialTopology = list(initialTopology)
        self.particleRadius = 20
        self.nodes = nodes
        self.physics = None
        self.X = 5
    def makeBond(self, source, dest):
        self.physics.particleDict[source].makeBond(self.physics.particleDict, dest)
    def makeParticle(self, label, position, nodetype, particleRadius):
        if position == "randompos":
           xpos = randrange(self.border, self.screensize[0]-self.border, 1)
           ypos = randrange(self.border, self.screensize[1]-self.border, 1)
           xpos,ypos = position
        particle = VisibleParticle( (xpos, ypos), label, particleRadius)
        self.physics.add( particle )
    def initialiseComponent(self):
        self.addHandler(MOUSEBUTTONDOWN, lambda event: ParticleDragger(event,self))
        self.addHandler(KEYDOWN, self.quit)
        self.laws    = Kamaelia.Support.Particles.SimpleLaws(bondLength = 100)
        self.physics = Kamaelia.Support.Particles.ParticleSystem(self.laws, [], 0)
        for node in self.nodes:
        for source,dest in self.initialTopology:
           self.makeBond(source, dest)
    def extra(self):
       if self.physics:
          if random.randrange(0,100)<5:
             self.makeParticle(str(self.X), "randompos", "circle", 20)
             self.X += 1
          if random.randrange(0,100)<25:
             start = self.physics.particleDict.keys()[random.randrange(0,len(self.physics.particleDict.keys()))]
             end = start
             while end == start:
                end = self.physics.particleDict.keys()[random.randrange(0,len(self.physics.particleDict.keys()))]
             self.makeBond(self.physics.particleDict[start].ID, self.physics.particleDict[end].ID)
    def mainLoop(self):
        self.screen.fill( (255,255,255) )
        for p in self.physics.particles:
        for p in self.physics.particles:
        return 1
    def drawGrid(self):
        for i in range(0,self.screen.get_height(), int(self.laws.maxInteractRadius)):
            pygame.draw.line(self.screen, (200,200,200),
                             (self.screen.get_width(),i) )
        for i in range(0,self.screen.get_width(), int(self.laws.maxInteractRadius)):
            pygame.draw.line(self.screen, (200,200,200), 
                             (i,self.screen.get_height()) )
if __name__=="__main__":
    N,L = 4,2
    nodes = []
    for i in xrange(N):
       nodes.append((str(i), "randompos", "circle", 20))
    linkDict = {}
    while len(linkDict.keys()) <L:
       start = random.randrange(0,len(nodes))
       end = start
       while end == start:
          end = random.randrange(0,len(nodes))
       linkDict[ nodes[start][0],nodes[end][0] ] = None
    links = linkDict.keys()
    app = PhysApp1( (640, 480), False, nodes, links)
    X = N+1
    for i in app.main():
       if randrange(0,100)<5:
          app.makeParticle(str(X), "randompos", "circle", 20)
          X += 1
       if randrange(0,100)<25:
          start = app.physics.particleDict.keys()[random.randrange(0,len(app.physics.particleDict.keys()))]
          end = start
          while end == start:
             end = app.physics.particleDict.keys()[random.randrange(0,len(app.physics.particleDict.keys()))]
          app.makeBond(app.physics.particleDict[start].ID, app.physics.particleDict[end].ID)