import math

from direct.showbase.DirectObject import DirectObject
from panda3d.core import PandaNode, NodePath
from pandac.PandaModules import CollisionSegment, CollisionNode, CollisionHandlerPusher, CollisionTraverser, CollisionSphere
from pandac.PandaModules import Vec3, Point3
from direct.task.Task import Task
from pandac.PandaModules import TextureStage, Texture
from pandac.PandaModules import ActorNode, CollisionHandlerEvent, CollisionHandlerGravity, CollisionHandlerPusher, CollisionNode, CollisionSphere, CollisionTraverser, BitMask32, CollisionRay, NodePath
from direct.interval.IntervalGlobal import *
from pandac.PandaModules import *
from direct.gui.OnscreenText import OnscreenText
from translation import *

from globals import *
from sprite2d import *
from enemy import npDic

class Player(DirectObject):

    def __init__(self, notifier,god=False):

        self.rootnp = render.attachNewNode(ActorNode("player root"))

        self.curAngle = 0
        self.onGround = True
        self.zSpeed = 0.0
        self.limit = 10.
        self.god = god
        self.txt = None

        #self.speed = 5.0
        self.curSpeed = 0.0

        self.isIndoor = True


        self.jumpsound = loader.loadSfx("sounds/jump.wav")
        self.jumpsound.setVolume(1.0)
        self.jumpsound.status() == AudioSound.PLAYING

        # Collision solids
        self.wallcollisionnp_top = self.rootnp.attachNewNode(CollisionNode('player collision node'))
        # self.wallcollisionnp_top.node().addSolid(CollisionSphere(0,0,1.5,0.5))
        # self.wallcollisionnp_top.node().setFromCollideMask(WALL_MASK)
        # self.wallcollisionnp_top.node().setIntoCollideMask(ALL_OFF)
        # self.wallcollisionnp_top.show()
        
        self.wallcollisionnp_btm = self.rootnp.attachNewNode(CollisionNode('player collision node'))
        # self.wallcollisionnp_btm.node().addSolid(CollisionSphere(0,0,0.6,0.5))
        # self.wallcollisionnp_btm.node().setFromCollideMask(WALL_MASK)
        # self.wallcollisionnp_btm.node().setIntoCollideMask(ALL_OFF)
        #self.wallcollisionnp_btm.show()

        self.sensor = self.rootnp.attachNewNode(CollisionNode('playersensor'))
        cs = CollisionSphere(0, 0, 1, 0.6)
        self.sensor.node().addSolid(cs)
        self.sensor.node().setFromCollideMask(FLOOR_MASK|TRIGGER_MASK)
        self.sensor.node().setIntoCollideMask(ALL_OFF)
        cs.setTangible(0)
        #self.sensor.show()

        self.ray = self.rootnp.attachNewNode(CollisionNode('avatarRay'))
        self.ray.node().addSolid(CollisionRay(0, 0, 0.1, 0, 0, -1))
        self.ray.node().setFromCollideMask(FLOOR_MASK)
        self.ray.node().setIntoCollideMask(ALL_OFF)
        
        self.collision_handler = notifier
        self.collision_handler.addCollider(self.ray, self.rootnp)

        self.rootnp.setCollideMask(ALL_OFF)
        self.model = loader.loadModel("models/player")
        self.model.setCollideMask(ALL_OFF)
        #self.model.reparentTo(self.rootnp)
        self.model.setBillboardAxis()


        #self.tex_rest = loader.loadTexture('models/Stance.png')


        self.sprite = Sprite2d("models/hero.png", rows=3, cols=9, scale=2, twoSided=True, anchorX="Center", anchorY="Bottom")
        self.sprite.node.reparentTo(self.rootnp)

        self.animateTask = taskMgr.add(self.textureMovie, "animateTask")
        self.animateTask.fps = 10
        self.animateTask.obj = self.model
        #self.animateTask.textures = self.textures
        self.canMove = True

        #self.rootnp.setPos(0,-25,-2.0)
        self.moveList = []
        self.collision_handler.addVelocity(15.0)

        self._x = self.rootnp.getX()
        self._hurt = 0.
        self.enemy = None
        self.life = 4
        self.star = 0
        self.dead = False
        self.dead_frame = 9
        self._dtf = 0.
        self._dts = 0.
        self.limit_z = -0.5

        self.planar = True

        #--- GUI ------------------------------

        self.node_gui = base.cam.attachNewNode("gui node")
        y = self.node_gui.getY(self.rootnp)
        self.node_gui.setY(y)
        self.sprite_star = Sprite2d("models/gui/star_cpt.png", rows=8, cols=2, scale=2, twoSided=True, anchorX="Center", anchorY="Bottom")
        self.sprite_star.node.reparentTo(self.node_gui)
        self.sprite_star.node.setPos(4.7, 1 ,3.8)
        
        self.sprite_x = Sprite2d("models/gui/0x.png", rows=1, cols=1, scale=2, twoSided=True, anchorX="Center", anchorY="Bottom")
        self.sprite_x.node.reparentTo(self.node_gui)
        self.sprite_x.node.setPos(5.2, 1 ,3.7)

        self.sprite_unity = Sprite2d("models/gui/chiffre.png", rows=1, cols=10, scale=2, twoSided=True, anchorX="Center", anchorY="Bottom")
        self.sprite_unity.node.reparentTo(self.node_gui)
        self.sprite_unity.node.setPos(4.6, 1 ,3.8)

        self.sprite_decimal = Sprite2d("models/gui/chiffre.png", rows=1, cols=10, scale=2, twoSided=True, anchorX="Center", anchorY="Bottom")
        self.sprite_decimal.node.reparentTo(self.node_gui)
        self.sprite_decimal.node.setPos(4.15, 1 ,3.8)

        self.sprite_hearts = Sprite2d("models/gui/hearts.png", rows=1, cols=5, scale=2, twoSided=True, anchorX="Center", anchorY="Bottom")
        self.sprite_hearts.node.reparentTo(self.node_gui)
        self.sprite_hearts.node.setPos(-4.7, 1 ,3.9)

    def updtCompteur(self):

        self.sprite_hearts.setFrame(self.life)
        if self.star < 0:
            self.star = 0.
       
        if self.star <= 0:
            self.sprite_unity.node.hide()
            self.sprite_decimal.node.hide()
            self.sprite_x.node.hide()
            if self.sprite_star.currentFrame < 15:
                dt = globalClock.getDt()
                self._dts += dt
                if self._dts >= 0.6:
                    self._dts = 0.
                self.sprite_star.setFrame(self.sprite_star.currentFrame + 1)
        else:

            self.sprite_star.setFrame(1)
            self.sprite_unity.setFrame(self.star%10)
            self.sprite_decimal.setFrame(int(self.star/10))


    def loadTextureMovie(self, frames, name, suffix, padding = 1):
        return [loader.loadTexture((name+"%0"+str(padding)+"d."+suffix) % (i+1) ) 
            for i in range(frames)]


    def toggle_wire(self, bloodyarg):
        base.toggleWireframe()
        base.toggleTexture()


    def textureMovie(self, task):
        self.updtCompteur()
        if self.txt != None:
            self._dtsay -= globalClock.getDt()
            if self._dtsay <=0:
                self.txt = None

        if self.dead:
            if self.dead_frame < 21:
                dt = globalClock.getDt()
                self._dtf += dt
                if self._dtf >= 0.2:
                    self._dtf = 0.
                    self.dead_frame += 1
                self.sprite.setFrame(self.dead_frame)
                
            else:
                self.sprite.setFrame(21)
            return Task.cont

        if self._hurt > 0.:
            currentFrame = int(task.time * 3) 
            self.sprite.setFrame(currentFrame % 2 + 7)
        else: 
            if self.curSpeed != 0:
                factor = 1
                # if self.curSpeed < 0:
                #     self.model.setTexScale(TextureStage.getDefault(), -1*factor, 1)
                # else:
                #     self.model.setTexScale(TextureStage.getDefault(),  1*factor, 1)
                currentFrame = int(task.time * task.fps) 
                #task.obj.setTexture(task.textures[currentFrame % len(task.textures)], 1)
                self.sprite.setFrame(currentFrame % 6)
            else:
                currentFrame = 0
                self.sprite.setFrame(6)
            if not self.collision_handler.isOnGround():
                self.sprite.setFrame(2)
        return Task.cont

    def sensorIn(self, entry):
        if self.dead:
            return
        np_into = entry.getIntoNodePath()
        if np_into.getName().find('star') >= 0:
            self.star -= 1
            np_into.getAncestor(3).removeNode()

        if np_into.getName().find('snake') >= 0:
            enemy = npDic[np_into.getAncestor(3)]
            ret = 0
            if not enemy.isDizzy:
                ret = enemy.checkCollide(self)

            if ret == 1:
                if self.collision_handler.isOnGround():
                    self.collision_handler.addVelocity(8)
                else:
                    self.collision_handler.addVelocity(20)

            elif ret == -1:
                self.hurt(enemy)

        if np_into.getName().find('centipede') >= 0:

            enemy = npDic[np_into.getAncestor(3)]
            ret = 0
            if not enemy.isDizzy:
                ret = enemy.checkCollide(self)

            if ret == 1:
                if self.collision_handler.isOnGround():
                    self.collision_handler.addVelocity(8)
                else:
                    self.collision_handler.addVelocity(20)

            elif ret == -1:
                self.hurt(enemy)


        if np_into.getName().find('pirate') >= 0:

            enemy = npDic[np_into.getAncestor(3)]
            ret = 0
            if not enemy.isDizzy:
                ret = enemy.checkCollide(self)

            if ret == 1:
                if self.collision_handler.isOnGround():
                    self.collision_handler.addVelocity(8)
                else:
                    self.collision_handler.addVelocity(20)

            elif ret == -1:
                self.hurt(enemy)



        if np_into.getName().find('spider') >= 0:
            enemy = npDic[np_into.getAncestor(3)]
            self.hurt(enemy)

        if np_into.getName().find('meatboy') >= 0:
            enemy = npDic[np_into.getAncestor(3)]
            self.hurt(enemy)

        if np_into.getName().find('bottle') >= 0:
            enemy = npDic[np_into.getAncestor(4)]
            if enemy.dead == False:
                self.hurt(enemy)
                enemy.erase()

    def hurt(self,enemy):
        if self.collision_handler.isOnGround():
            self.collision_handler.addVelocity(8)
        else:
            self.collision_handler.addVelocity(20)

        self._hurt = 0.4
        self.enemy = enemy
        if not self.god:
            self.life -= 1
        if self.life < 0:
            self.life = 0

    def dead(self):
        self.dead = True
   

    def onPlatform(self, entry):
        self.zSpeed = 0.0

    def move(self):
        #print self.rootnp.getX()
        if self.rootnp.getZ() < self.limit_z:
            if not self.god:
                self.dead = True

        if self.dead == True:
            return

        dt = globalClock.getDt()

        #--- constante -----------
        decel = 0.5
        speedMax = 0.2
        jumpPower = 12

         #--- sens -----------------

        sens_sp = 0
        if self.curSpeed > 0.:
            sens_sp = 1
        elif self.curSpeed < 0.:
            sens_sp = -1

        if self._hurt > 0.:
            self._hurt -= dt
            self.moveList = []

            dx = self.rootnp.getX(self.enemy.rootnp)
            sens = 1
            if dx < 0:
                sens = -1
            self.curSpeed = 0.1*sens

            if self._hurt <= 0.0:
                self._hurt = 0.0
                if self.life <= 0:
                    self.dead = True

        dx =  abs(self.rootnp.getX() - self._x)
        if dx <= 0.00001:
            self.curSpeed = 0.0
        self._x = self.rootnp.getX()

        if len(self.moveList) == 0:

            if self.curSpeed != 0.0:
                self.curSpeed -= sens_sp * decel * dt

                if self.curSpeed >= -0.05 and self.curSpeed <= 0.05:
                    self.curSpeed = 0.0

        else:
            if 'left' in self.moveList or 'right' in self.moveList:

                #--- sens -----------------
                sens = 0
                if 'right' in self.moveList:
                    sens = 1
                elif 'left' in self.moveList:
                    sens = -1

                speed = 0.1

                if sens_sp != sens:
                    speed += decel

                self.curSpeed += speed * dt * sens
                if abs(self.curSpeed) > speedMax:
                    self.curSpeed = speedMax * sens
                if self.rootnp.getX() < 0.:
                    self.rootnp.setX(0.0)
                    self.curSpeed = 0.

                if self.rootnp.getX() > self.limit and self.star > 0:
                    self.rootnp.setX(self.limit)
                    self.curSpeed = 0.

            if 'jump' in self.moveList:
                if self.collision_handler.isOnGround():
                    self.collision_handler.addVelocity(jumpPower)
                    self.jumpsound.play()

        #print self.curSpeed
        if self._hurt > 0.:
            if self.curSpeed > 0.:
                #pass
                self.sprite.flipX(True)
            elif self.curSpeed <0.:
                self.sprite.flipX(False)
        else:
            if self.curSpeed > 0.:
                #pass
                self.sprite.flipX(False)
            elif self.curSpeed <0.:
                self.sprite.flipX(True)

        self.rootnp.setX(self.rootnp,self.curSpeed)
