import plus
import random
from AI import vector3

import Arenas

class Hazard(object):
    def __init__(self, location):
        self.location = location

class Flame(Hazard):

    def __init__(self, location = (0, 0, 0), velocity = (0, 0, 0), variance = (0, 0, 0), yOffset = 0):
        Hazard.__init__(self, location)
        self.refcount = 0
        self.velocity = velocity
        self.variance = variance
        self.emitter = plus.AddParticleEmitter(self.location, self.velocity, self.variance)
        self.emitting = False
        self.timeEmitting = 0
        self.adjustedLoc = vector3(self.location)
        self.adjustedLoc.y += yOffset
        self.flamesound = plus.createSound("Sounds/flame_throwerquiet.wav", True, self.location)
        
    def __del__(self):
        plus.removeSound(self.flamesound)
        
    def Tick(self):
        if self.emitting==True:
            if plus.isMatchOver():
                self.FlameOff()
                
            if self.timeEmitting<1:     #flames are long enough by the end of 1 second
                self.timeEmitting += .25
            
            vel = vector3(self.velocity)
            flamepos = vel * self.timeEmitting
            flamepos = flamepos + vector3(self.location)
            arena = Arenas.currentArena
            if arena:
                compinfo = plus.rayTest(self.adjustedLoc.asTuple(), flamepos.asTuple())
                if not compinfo[0]==-1:  # we got a valid bot and component back from the ray test
                    if not plus.isMatchPaused() and not plus.isMatchOver():
                        plus.damage(compinfo[0], compinfo[1], 30, (compinfo[2], compinfo[3], compinfo[4]))
    
    def FlameOff(self):
        self.emitter.SetEmitting(False)
        self.emitting = False
        plus.stopSound(self.flamesound)
    
    def FlameOn(self):
        self.emitter.SetEmitting(True)
        self.emitting = True
        plus.loopSound(self.flamesound)
        self.timeEmitting = 0
    
    def ZoneEvent(self, direction):
        if direction==1:
            self.refcount+= 1
            if self.refcount == 1:
                self.FlameOn()
        elif direction==-1:
            self.refcount -= 1
            if self.refcount == 0:
                self.FlameOff()

class Saws(Hazard):

    def __init__(self, a_prismatic, location = (0, 0, 0)):
        Hazard.__init__(self, location)
        #statuses: 0=off, 1=on
        self.status = 0
        self.prismatic = a_prismatic
        self.prismatic.SetAutoLock(False)
        self.prismatic.SetPowerSettings(.001, -150000)
        self.timer = 0
        self.refcount = 0
	self.moved = 0
	self.prismatic.Lock(True)
        self.slidesound = plus.createSound("Sounds\\hzd_trapdoor_loop.wav", True, self.location)

    def __del__(self):
        plus.removeSound(self.slidesound)


    def ZoneEvent(self, direction):
        if direction ==1:
		self.refcount += 1
		self.MoveSaw(1)
 		self.status = 1
	    
	elif direction == -1:
        	self.refcount -= 1
	   
    def Tick(self):
        if self.status == 1:
	    self.timer += .5
	    if self.timer == 6: self.StopSaw(0)
            
    def MoveSaw(self, dir):
	if self.moved ==0:
	    self.status = 1
	    self.moved = 1
            self.prismatic.Lock(False)
            self.prismatic.SetDirection(dir)
	    plus.loopSound(self.slidesound)

    def StopSaw(self, dir):
	self.status = 0
        self.prismatic.SetDirection(0)
        #self.prismatic.Lock(True)
        plus.stopSound(self.slidesound)

class Electricity(Hazard):

    def __init__(self, location = (0, 0, 0)):
        Hazard.__init__(self, location)
        self.chargetimer = 0.0
        self.zaptimer = 0.0
        self.announcetimer = 12.0
        self.sensors = {}
        self.zapping = []
        self.zapsound = plus.createSound("Sounds/zap_loop.wav", True, self.location)
        self.chargesound = plus.createSound("Sounds/zap_charge2.wav", True, self.location)
        self.announcer = (plus.createSound("Sounds/announcers/Misc_NowThatsAnEnergizer.wav", True, self.location), plus.createSound("Sounds/announcers/Misc_ShockingDisplayOfPower.wav", True, self.location), plus.createSound("Sounds/announcers/Misc_ThereGoesTheElectricBill.wav", True, self.location), plus.createSound("Sounds/announcers/Misc_UpTheVoltage.wav", True, self.location), plus.createSound("Sounds/announcers/Misc_JumpStart.wav", True, self.location))
    
    def __del__(self):
        plus.removeSound(self.zapsound)
        plus.removeSound(self.chargesound)
        
        for x in self.announcer:
            plus.removeSound(x)
        
        self.announcer = ()

    def Tick(self):
        self.announcetimer -= .25
        if self.chargetimer==0.0 and self.NumBotsInRange()==1:
            self.Zap()
            
        if self.zaptimer>0.0:
            self.zaptimer-=.25
            if self.zaptimer<=0.0:
                self.zaptimer = 0.0
                self.zapping = []
                plus.stopSound(self.zapsound)
            elif self.zaptimer>0.0:
                for bot in self.zapping:
                    if not plus.isMatchPaused() and not plus.isMatchOver():
                        plus.damage(bot, 0, 10, plus.getLocation(bot))
                        if self.sensors[bot]:
                            plus.force(bot, 0, 115 * plus.getWeight(bot), 0)
            
        if self.chargetimer > 0.0:
            self.chargetimer -= .25
        elif self.chargetimer<0.0:
            self.chargetimer = 0.0

    def Zap(self):
        if not plus.isMatchPaused() and not plus.isMatchOver():
            if self.chargetimer==0.0:
                for bot, in_range in self.sensors.iteritems():
                    if in_range:
                        plus.zap(bot, 10, 3.0)
                        self.zapping.append(bot)
                        self.zaptimer = 3.0
                        self.chargetimer = 5.0
                        Arenas.currentArena.Charge(self.chargetimer, self.sensors)
                        plus.loopSound(self.zapsound)
                        plus.playSound(self.chargesound)
                        if self.announcetimer <= 0:
                            plus.playSound(random.choice(self.announcer))
                            self.announcetimer = 12.0
        
    def Button(self):
        self.Zap()
        
    def NumBotsInRange(self):
        numBots = 0
        for bot, in_range in self.sensors.iteritems():
            if in_range: numBots += 1
                
        return numBots
        
    def ZoneEvent(self, direction, robot, chassis):
        if chassis:
            r = robot - 1
            if r not in self.sensors: self.sensors[r] = 0
            
            if direction==1:
                self.sensors[r] += 1
            elif direction==-1:
                self.sensors[r] -= 1

class Spikes(Hazard):
    
    def __init__(self, a_prismatic, a_power, location = (0, 0, 0)):
        Hazard.__init__(self, location)
        #statuses: 0=waiting, 1=firing
        self.status = 0
        self.prismatic = a_prismatic
        self.power = a_power
        self.prismatic.SetAutoLock(False)
        self.timer = 0
        self.refcount = 0
        self.firesound = plus.createSound("Sounds\\hzd_pusher_fire.wav", True, self.location)
        
    def __del__(self):
        plus.removeSound(self.firesound)
        
    def ZoneEvent(self, direction):
        if direction==1:
            self.timer = 0
            self.status = 1
            self.refcount += 1
        elif direction==-1:
            self.refcount -= 1
            if self.refcount == 0: self.status = 0
            
    def Tick(self):
        if self.status==1:
            self.timer += .5
            if self.timer == 0.5: self.FireTeeth()
            if self.timer == 3.5: self.timer = 0
            
    def FireTeeth(self):
        plus.playSound(self.firesound)
        self.prismatic.Lock(False)
        self.prismatic.ApplyForce(self.power)

class PitDropper(Hazard):

    def __init__(self, a_prismatic, location = (0, 0, 0)):
        Hazard.__init__(self, location)
        #statuses: 0=off, 1=on
        self.status = 0
        self.prismatic = a_prismatic
        self.prismatic.SetAutoLock(False)
        self.prismatic.SetPowerSettings(0.00001, -580)
        self.timer = 0
        self.refcount = 0
	self.moved = 0
	self.prismatic.Lock(True)
        self.slidesound = plus.createSound("Sounds\\hzd_trapdoor_loop.wav", True, self.location)

    def __del__(self):
        plus.removeSound(self.slidesound)


    def ZoneEvent(self, direction):
        if direction ==1:
		self.refcount += 1
		self.MoveSaw(1)
 		self.status = 1
	    
	elif direction == -1:
        	self.refcount -= 1
	   
    def Tick(self):
        if self.status == 1:
	    self.timer += .5
	    if self.timer == 10.5: self.StopSaw(0)
            
    def MoveSaw(self, dir):
	if self.moved ==0:
	    self.status = 1
	    self.moved = 1
            self.prismatic.Lock(False)
            self.prismatic.SetDirection(dir)
	    plus.loopSound(self.slidesound)

    def StopSaw(self, dir):
	self.status = 0
        self.prismatic.SetDirection(0)
        self.prismatic.Lock(True)
        plus.stopSound(self.slidesound)

class Saws2(Hazard):

    def __init__(self, a_prismatic, location = (0, 0, 0)):
        Hazard.__init__(self, location)
        #statuses: 0=off, 1=on
        self.status = 0
        self.prismatic = a_prismatic
        self.prismatic.SetAutoLock(False)
        self.prismatic.SetPowerSettings(0.002, -580000)
        self.timer = 0
        self.refcount = 0
	self.lstopper = 0
        self.callcount = 0

    def ZoneEvent(self, direction):
        if direction ==1:
		self.refcount += 1
 		if self.refcount == 2: self.MoveSaw(1)
		if self.refcount == 2: self.status = 1
 		if self.refcount == 2: self.lstopper = 0
 		if self.refcount == 2: self.timer = 1

	    
	elif direction == -1:
		if self.refcount == 2: self.lstopper = 1
        	self.refcount -= 1
	   


    def CallLift(self, direction):
	if direction ==1:
		self.callcount += 1
	    	if self.callcount == 1: self.MoveSaw(-1)        	    
	    	if self.callcount == 1: self.status = 0
            	if self.callcount == 1: self.timer = 0	    
	    	if self.callcount == 1: self.lstopper = 0
		if self.callcount == 1: self.refcount = 1
	
	elif direction == -1:
		 self.callcount = 0

    def Tick(self):
            if self.status == 1:
		if self.lstopper == 2: self.timer += .5
		if self.lstopper == 1: self.StopSaw(0)
		if self.lstopper == 1: self.lstopper = 2
	    	if self.timer == 40: self.MoveSaw(-1)
           	if self.timer == 41: self.status = 0
		if self.timer == 42: self.timer = 0
            
    def MoveSaw(self, dir):
        self.prismatic.Lock(False)
        self.prismatic.SetDirection(dir)

    def StopSaw(self, dir):
        self.prismatic.Lock(True)
        self.prismatic.SetDirection(dir)

class RWFlipper(Hazard):
    
    def __init__(self, a_hinge, location = (0, 0, 0)):
        Hazard.__init__(self, location)
        #statuses: 0=waiting, 1=firing
        self.status = 0
        self.hinge = a_hinge
        self.hinge.SetAutoLocks(False, False)
        self.hinge.Lock(True)
        self.timer = 0
        self.soundHandle = plus.createSound("Sounds\\hellraiser_trigger.wav", 1, (0, 0, 0))
        
    def __del__(self):
        plus.removeSound(self.soundHandle)
        
    def Tick(self):
        if self.status == 1: self.timer += .5
        if (self.status == 1 and self.timer > 6.5):
            self.LowerHell()
	if self.timer == 5.5:
	    self.hinge.SetPowerSettings(150,4000)
            self.hinge.Lock(False)
            self.hinge.SetDirection(100)
            plus.playSound(self.soundHandle)
                
    def RaiseHell(self):
        self.status = 1
        
    def LowerHell(self):
        self.hinge.SetPowerSettings(4, 200)
        self.hinge.Lock(False)
        self.hinge.SetDirection(-100)
        self.timer = 0
        self.status = 0
	self.dropnow = 0

        
class HellRaiser(Hazard):
    
    def __init__(self, a_hinge, location = (0, 0, 0)):
        Hazard.__init__(self, location)
        #statuses: 0=waiting, 1=firing
        self.status = 0
        self.hinge = a_hinge
        self.hinge.SetAutoLocks(False, False)
        self.hinge.Lock(True)
        self.timer = 0
        self.soundHandle = plus.createSound("Sounds\\nelson.wav", 1, (0, 0, 0))
       
    def __del__(self):
        plus.removeSound(self.soundHandle)
        plus.removeSound(self.soundpandle)
        
    def Tick(self):
        if self.status == 1: self.timer += .5
        if (self.status == 1 and self.timer > 3.5):
            self.LowerHell()
                
    def RaiseHell(self):
        self.status = 1
	self.hinge.SetPowerSettings(20,4000)
        self.hinge.Lock(False)
        self.hinge.SetDirection(100)
        plus.playSound(self.soundHandle)
        
    def LowerHell(self):
        self.hinge.SetPowerSettings(4, 200)
        self.hinge.Lock(False)
        self.hinge.SetDirection(-100)
        self.timer = 0
        self.status = 0
	self.dropnow = 0

class Spinner(Hazard):
    
    def __init__(self, a_hinge, location = (0, 0, 0)):
        Hazard.__init__(self, location)
        #statuses: 0=waiting, 1=firing
        self.status = 0
        self.hinge = a_hinge
        self.hinge.SetAutoLocks(False, False)
        self.hinge.Lock(True)

        
    def __del__(self):
        plus.removeSound(self.soundHandle)
        

                
    def Spin(self):
        self.hinge.SetPowerSettings(35,150000)
        self.hinge.Lock(False)
        self.hinge.SetDirection(100)
	self.hinge.ApplyTorque(10)


class Blade(Hazard):
    
    def __init__(self, a_hinge, location = (0, 0, 0)):
        Hazard.__init__(self, location)
        #statuses: 0=waiting, 1=firing
        self.status = 0
        self.hinge = a_hinge
        self.hinge.SetAutoLocks(False, False)
        self.hinge.Lock(True)

        
    def __del__(self):
        plus.removeSound(self.soundHandle)
        

                
    def Spin(self):
        self.hinge.SetPowerSettings(12,150000)
        self.hinge.Lock(False)
        self.hinge.SetDirection(100)
	self.hinge.ApplyTorque(10)

class Lift(Hazard):

    def __init__(self, a_prismatic, location = (0, 0, 0)):
        Hazard.__init__(self, location)
	self.status = 0
	self.timer = 0
        self.prismatic = a_prismatic
        self.prismatic.SetAutoLock(True)
        self.prismatic.SetPowerSettings(0.001, 2000)
        self.firesound = plus.createSound("Sounds\\liftmove.wav", True, self.location)
        self.stopsound = plus.createSound("Sounds\\LiftTing.wav", True, self.location)
        self.upsound = plus.createSound("Sounds\\crate.wav", True, self.location)


    def MoveUp(self, dir, bot):
        self.prismatic.SetAutoLock(False)
	mass = plus.getWeight(bot)
	self.timer = 0
	self.status = 1
	self.prismatic.SetPowerSettings(0.01, (2000 + (7.5*mass)))
	self.prismatic.Lock(False)
	self.prismatic.SetDirection(dir)
	plus.playSound(self.firesound)

    def MoveDown(self, dir, bot):
        self.prismatic.SetAutoLock(False)
	mass = plus.getWeight(bot)
	self.timer = 0
	self.status = 1
	self.prismatic.SetPowerSettings(0.001, (2000))
	self.prismatic.Lock(False)
	self.prismatic.SetDirection(-1*dir)
	plus.playSound(self.firesound)

    def CallUp(self, dir):
        self.prismatic.SetAutoLock(True)
	self.timer = 0
	self.status = 1
	self.prismatic.SetPowerSettings(0.001, 3000)
	self.prismatic.Lock(False)
        self.prismatic.SetAutoLock(True)
	self.prismatic.SetDirection(dir)
	plus.playSound(self.firesound)

    def CallDown(self, dir):
        self.prismatic.SetAutoLock(True)
	self.timer = 0
	self.status = 1
	self.prismatic.SetPowerSettings(0.001, 1000)
	self.prismatic.Lock(False)
	self.prismatic.SetDirection(dir)
	plus.playSound(self.firesound)

    def StopLift(self):
	self.prismatic.Lock(True)
	plus.playSound(self.upsound)
	plus.playSound(self.stopsound)

    def Bing(self):
	plus.playSound(self.stopsound)


class LiftDropper(Hazard):
    
    def __init__(self, a_prismatic, location = (0, 0, 0)):
        Hazard.__init__(self, location)
	self.timer = 0
	self.status = 0
        self.prismatic = a_prismatic
        self.prismatic.SetAutoLock(False)

        self.backsound = plus.createSound("Sounds\\burst_trigger.wav", True, self.location)

    def DropLift(self):
	self.prismatic.Lock(False)
	self.timer = 0
	self.status = 1
        plus.playSound(self.backsound)
	self.prismatic.ApplyForce(180000)


    def StopLatch(self):
	self.prismatic.Lock(False)
	self.prismatic.ApplyForce(-18000)

    def Tick(self):
	if self.status ==1: 
	    self.timer +=.5
	    if self.timer == 6: 
	        self.StopLatch()
	        self.status = 0

