from sprite2d import *
from panda3d.core import PandaNode, NodePath
from direct.task.Task import Task
from random import randint
import math 
from globals import *

#--- Variables globales -------

enemyList = []
bottleSpawnList = []
npDic = {}



class Enemy():

    def __init__(self, nodepath, sprite, rows = 1, cols = 1, scale = 2,fps = 10,lvl = '1',number = ''):
        self.rootnp = nodepath
        npDic[self.rootnp] =  self
        self.type = 'ennemy'
        self.frameWalkMax = 0
        self.dizzyFrame = 0
        datafile = 'models/level'+ str(lvl) +'/'
        self.geom = loader.loadModel(datafile +sprite)
        self.geom.reparentTo(self.rootnp)
        self.fps = fps
        self.name =  sprite
        self.dead = False


        for coll in self.geom.findAllMatches("**/"+ sprite + "_trigger*"):
            coll.node().setIntoCollideMask(TRIGGER_MASK)

        self.sprite = Sprite2d(datafile + sprite + str(number)+ '.png', rows=rows, cols=cols, scale=scale, twoSided=True, repeatX=1, anchorX="Center", anchorY="Center")
        self.sprite.node.reparentTo(self.rootnp)

        self.animateTask = taskMgr.add(self.textureMovie, "animateTask")

        #--- variable -------------------------------
        self.speed = 0.8
        self.positionInit = self.rootnp.getX(),self.rootnp.getZ()
        self.sens = -1
        self.distance = 10.
        self.isDizzy =  False
        self.time_to_dizzy = 3.
        self._dizzy = 0.
        self.invincible = False

        #--- add to list -----------------------------

        enemyList.append(self)
        self.limitjump = -0.97

    def textureMovie(self, task):
        factor = 1
        # if self.curSpeed < 0:
        #     self.model.setTexScale(TextureStage.getDefault(), -1*factor, 1)
        # else:
        #     self.model.setTexScale(TextureStage.getDefault(),  1*factor, 1)
        if not self.isDizzy:
            currentFrame = int(task.time * self.fps)
            if currentFrame != 0.0:
                self.sprite.setFrame(currentFrame % self.frameWalkMax)

        return Task.cont

    def move(self):

        dt = globalClock.getDt()

        if self.isDizzy:
            self._dizzy += dt
            self.sprite.setFrame(self.dizzyFrame)
            if self._dizzy >= self.time_to_dizzy:
                self._dizzy = 0.
                self.isDizzy = False
        else:

            self.rootnp.setX(self.rootnp,dt*self.speed*self.sens)

            if self.sens == -1:
                if self.rootnp.getX() <= self.positionInit[0] - self.distance:
                    self.sens = 1
                    self.rootnp.setX(self.positionInit[0] - self.distance)
                    self.sprite.flipX()
            elif self.sens == 1:
                if self.rootnp.getX() >= self.positionInit[0]:
                    self.sens = -1
                    self.rootnp.setX(self.positionInit[0])
                    self.sprite.flipX()

    def checkCollide(self,player):
        
        pz = player.rootnp.getZ(self.rootnp) #le 0.6 c'est pour decenterun peu le point impact
        print pz
        if pz > self.limitjump and not self.invincible:
            self.dizzy()
            return 1
        else:
            return -1

        return 0

    def dizzy(self):
        self.isDizzy = True



def shootBottle(task):
    bsl = [b for b in bottleSpawnList if b.start_to_fire]
    bt =  [b for b in enemyList if b.type == 'bottle']
    if len (bsl) > 0:
        bsl = [b for b in bottleSpawnList if b.start_to_fire]
        b = bsl[randint(0,len(bsl)-1)]
        if len (bt) < 1:
            b.shoot()

        for ob in bsl:
            if ob != b:
                ob.shoot(True)
    return Task.cont


class Snake(Enemy):
    def __init__(self, nodepath):
        Enemy.__init__(self,nodepath,'snake',cols=3,fps=5)
        self.frameWalkMax = 1
        self.dizzyFrame = 2
        self.limitjump = -0.97

class Centipede(Enemy):
    def __init__(self, nodepath):
        Enemy.__init__(self,nodepath,'centipede',cols=4, scale = 4,fps=5,lvl =2)
        self.frameWalkMax = 2
        self.dizzyFrame = 3
        self.limitjump = -0.97
        self.distance = 2.5

class Pirate(Enemy):
    def __init__(self, nodepath):
        n = randint(1,3)
        Enemy.__init__(self,nodepath,'pirate',cols=8,rows=2,fps=5,lvl=5,number=n)
        self.frameWalkMax = 7
        self.dizzyFrame = 14
        self.limitjump = -0.97
        self.distance = 3
        self.sens = 1

    def textureMovie(self, task):
        Enemy.textureMovie(self,task)
        if self.isDizzy:
            currentFrame = int(task.time * self.fps)
            if currentFrame != 0.0:
                self.sprite.setFrame(currentFrame % 2 + self.dizzyFrame)

        return Task.cont

    def move(self):

        dt = globalClock.getDt()

        if self.isDizzy:
            self._dizzy += dt
            self.sprite.setFrame(self.dizzyFrame)
            if self._dizzy >= self.time_to_dizzy:
                self._dizzy = 0.
                self.isDizzy = False
        else:

            self.rootnp.setX(self.rootnp,1*dt*self.speed*self.sens)

            if self.sens == -1:
                if self.rootnp.getX() <= self.positionInit[0] :
                    self.sens = 1
                    self.rootnp.setX(self.positionInit[0])
                    self.sprite.flipX()
            elif self.sens == 1:
                if self.rootnp.getX() >= self.positionInit[0] + self.distance:
                    self.sens = -1
                    self.rootnp.setX(self.positionInit[0] + self.distance)
                    self.sprite.flipX()



class Spider(Enemy):
    def __init__(self, nodepath):

        Enemy.__init__(self,nodepath,'spider',cols=2,scale = 4, fps=5,lvl=2)
        self.frameWalkMax = 1
        self.invincible = True
        self.distance = 3.

    def move(self):
        dt = globalClock.getDt()
        self.rootnp.setZ(self.rootnp,dt*self.speed*self.sens)

        if self.sens == -1:
            if self.rootnp.getZ() <= self.positionInit[1] - self.distance:
                self.sens = 1
                self.rootnp.setZ(self.positionInit[1] - self.distance)
        elif self.sens == 1:
            if self.rootnp.getZ() >= self.positionInit[1]:
                self.sens = -1
                self.rootnp.setZ(self.positionInit[1])

    def textureMovie(self, task):
        factor = 1
        # if self.curSpeed < 0:
        #     self.model.setTexScale(TextureStage.getDefault(), -1*factor, 1)
        # else:
        #     self.model.setTexScale(TextureStage.getDefault(),  1*factor, 1)
        if not self.isDizzy:
            currentFrame = int(task.time * self.fps)
            if currentFrame != 0.0:
                self.sprite.setFrame(currentFrame % self.frameWalkMax)

        return Task.cont

class MeatBoy(Enemy):
    def __init__(self, nodepath):

        Enemy.__init__(self,nodepath,'meatboy',cols=1,scale = 2, fps=5,lvl=5)
        self.frameWalkMax = 0
        self.invincible = True

    def move(self):
        pass
    def textureMovie(self, task):
        pass





class BottleSpawn():
    def __init__(self,nodepath,player):
        bottleSpawnList.append(self)
        self.rootnp = nodepath
        self.animateTask = taskMgr.add(self.checkReach, "check reach")
        self.reach = 4
        self.player =  player
        self.start_to_fire =  False
        self.time = 0.0
        

    def checkReach(self, task):
        #--- constantes ------------------
        time_reload = 4.

        dt = globalClock.getDt()
        self.time += dt

        if self.time >= time_reload:
            dm = abs(self.player.rootnp.getX(self.rootnp)) + abs(self.player.rootnp.getZ(self.rootnp))
            if dm <= self.reach:
                self.start_to_fire = True
        else:
            self.start_to_fire =  False

        return Task.cont


    def shoot(self,empty = False):
        global enemyList
        if not empty:
            enemyList.append(Bottle(self.rootnp,self.player))
        self.time = 0.0
        self.start_to_fire = False

class Bottle():
    def __init__(self, nodepath,player):
        node = nodepath.attachNewNode('bottle node')
        self.rootnp = node
        self.rotatenp = self.rootnp.attachNewNode('bottle rotate')
        self.type = 'bottle'
        self.vector = player.rootnp.getPos(self.rootnp)
        self.geom = loader.loadModel('models/level1/bottle')
        self.geom.reparentTo(self.rotatenp)

        self.fps = 10
        self.sprite = Sprite2d('models/level1/bottle.png', rows=1, cols=1, scale=5, twoSided=True, repeatX=1, anchorX="Center", anchorY="Center")
        self.sprite.node.reparentTo(self.rotatenp)
        npDic[self.rootnp] =  self
        self.dead = False

    def move(self):
        #--- Constante --------
        speed = 2.

        dt = globalClock.getDt()
        self.rotatenp.setR(self.rotatenp,160 * dt)

        norm = max(math.sqrt(self.vector[0]**2 + self.vector[2]**2),000000000.1)
        vec = self.vector[0]/norm, self.vector[2]/norm
        vec = vec[0] * speed , vec[1] * speed

        self.rootnp.setX(self.rootnp,vec[0]*dt)
        self.rootnp.setZ(self.rootnp,vec[1]*dt)

        
        if self.rootnp.getZ(base.render) <= 0.:
            enemyList.remove(self)
            self.rotatenp.removeNode()
            self.sprite = Sprite2d('models/level1/bottle_broken.png', rows=1, cols=1, scale=8, twoSided=True, repeatX=1, anchorX="Center", anchorY="Center")
            self.sprite.node.reparentTo(self.rootnp)

    def erase(self):
        enemyList.remove(self)
        self.sprite.node.removeNode()
        self.dead = True

