class PlayWidget(Widget):
    frameNum = 0
    score = 0
    enemies = []
    player1 = None
    player2 = None
    world = None

    roundFrames = FRAMERATE * 30

    def __init__(self, **kwargs):
        super(PlayWidget, self).__init__(**kwargs)

        # 330, 220
        playRect = Rectangle(pos=(50, 40), size=(610, 400))

        self.enemyGroup = InstructionGroup()

        self.world = World()

        # Create Players
        self.player1 = Player('p1')

        self.player2 = Player('p2')

        # Create Beam
        self.beam = Beam(self.player1, self.player2)

        # Create Score Label
        self.scoreLabel = Label(text='', pos=(295, 400))
        self.timerLabel = Label(text='', pos=(560, 350),
                                font_size=100, halign='right')
        self.updateScoreDisplay()
        self.updateTimerDisplay()

        # Background
        self.canvas.add(Color(0.2, 0.2, 0.2))
        #self.canvas.add(playRect)
        self.canvas.add(self.enemyGroup)
        self.canvas.add(self.beam.canvas)
        self.canvas.add(self.player1.canvas)
        self.canvas.add(self.player2.canvas)
        self.canvas.add(self.scoreLabel.canvas)
        self.canvas.add(self.timerLabel.canvas)

        self.timeOfLastSpawn = 0
        self.nextSpawnIn = 0
        self.shouldClose = False

    def setKeyReport(self, keyReport):
        self.keyReport = keyReport
        self.beam.setKeyReport(keyReport)

    def reset(self):
        self.shouldClose = False
        self.frameNum = 0
        self.world.reset()
        self.player1.reset()
        self.player2.reset()
        self.beam.reset()
        self.player1.setCenterPos((200, 220))
        self.player2.setCenterPos((460, 220))
        self.score = 0
        self.timeOfLastSpawn = 0
        self.nextSpawnIn = 0

    def cleanup(self):
        self.enemyGroup.clear()
        self.enemies = []

    def spawnEnemy(self, enemyType):
        enemy = Enemy(enemyType)
        enemy.reset(False)
        enemy.setWorld(self.world)
        self.enemyGroup.add(enemy.canvas)

        centerPos = self.world.nextEnemyPos(enemy.offsetTheta)
        enemy.setCenterPos(centerPos)
        self.enemies.append(enemy)

    def update(self, dt):
        self.frameNum += 1

        if self.frameNum > self.roundFrames:
            self.shouldClose = True
            return

        if self.frameNum % FRAMERATE == 0:
            self.updateTimerDisplay()

        self.world.update(dt)

        # Update Players
        self.player1.update(dt)
        self.player2.update(dt)

        self.spawnNewEnemies()

        # Update Enemies
        for enemy in self.enemies:
            enemy.update(dt)

        if self.beam.beamState == 0:
            self.beam.setIsColliding(False)
        else:
            collisions = self.getCollisions()
            if len(collisions) > 0:
                self.beam.setIsColliding(True)
                self.consumeEnemies(collisions, self.beam.beamState)
            else:
                self.beam.setIsColliding(False)

        self.clearDeadEnemies()

        # Update Beam
        self.beam.update(dt)

    def consumeEnemies(self, collisions, beamState):
        totalDelta = 0
        for enemy in collisions:
            delta = enemy.decrement(beamState)
            totalDelta += delta

        if not totalDelta == 0:
            self.score += totalDelta
            self.updateScoreDisplay()

    def updateScoreDisplay(self):
        self.scoreLabel.text = 'Score: ' + str(self.score)

    def updateTimerDisplay(self):
        seconds = int(math.ceil((self.roundFrames - self.frameNum) / FRAMERATE))
        if seconds > 5:
            self.timerLabel.color[3] = 0.3
        else:
            self.timerLabel.color[3] = 1
        if seconds > 3:
            self.timerLabel.color[0] = 1
            self.timerLabel.color[1] = 1
            self.timerLabel.color[2] = 1
        else:
            self.timerLabel.color[0] = 0.6
            self.timerLabel.color[1] = 0
            self.timerLabel.color[2] = 0

        self.timerLabel.text = str(seconds)

    def spawnNewEnemies(self):
        if self.timeOfLastSpawn + self.nextSpawnIn > self.frameNum:
            return

        enemyType = 'normal'
        if random.random() < 0.3:
            enemyType = 'other'
        self.spawnEnemy(enemyType)
        self.timeOfLastSpawn = self.frameNum

        if self.frameNum < 200:
            self.nextSpawnIn = 10


    def clearDeadEnemies(self):
        deadEnemies = []

        for enemy in self.enemies:
            if enemy.shouldRemove:
                deadEnemies.append(enemy)

        if len(deadEnemies) == 0:
            return

        aliveEnemies = []
        for enemy in self.enemies:
            if not enemy.shouldRemove:
                aliveEnemies.append(enemy)

        # rebuild
        self.enemyGroup.clear()
        for enemy in aliveEnemies:
            self.enemyGroup.add(enemy.canvas)

        self.enemies = aliveEnemies


    def getCollisions(self):
        beamLineCoords = (self.player2.pos[0], self.player2.pos[1], self.player1.pos[0], self.player1.pos[1])
        collisions = []

        for enemy in self.enemies:
            if enemy.sprite.collidesWithLine(beamLineCoords):
                collisions.append(enemy)

        return collisions