import tidal
import random
from app import App
import vga2_8x8 as default_font

UP = 1
DOWN = 2
LEFT = 3
RIGHT = 4

class Snake(App):
    def on_start(self):
        super().on_start()
    
    def on_activate(self):
        super().on_activate()
        self.buttons.on_press(tidal.JOY_UP, lambda: self.set_direction(UP))
        self.buttons.on_press(tidal.JOY_DOWN, lambda: self.set_direction(DOWN))
        self.buttons.on_press(tidal.JOY_LEFT, lambda: self.set_direction(LEFT))
        self.buttons.on_press(tidal.JOY_RIGHT, lambda: self.set_direction(RIGHT))
        self.game_restart()

    def set_direction(self, dir):
        # this joystick makes it annoyingly easy to kill yourself by doing a 180
        # by accident, so only allow the direction to change by 90 degrees at a time
        if self.direction == UP or self.direction == DOWN:
            if dir == LEFT or dir == RIGHT:
                self.direction = dir
        elif self.direction == LEFT or self.direction == RIGHT:
            if dir == UP or dir == DOWN:
                self.direction = dir

    def update(self):
        new_x = self.body[0][0]
        new_y = self.body[0][1]
        if self.direction == UP:
            new_y -= 8
        elif self.direction == DOWN:
            new_y += 8
        elif self.direction == LEFT:
            new_x -= 8
        elif self.direction == RIGHT:
            new_x += 8
        new_y %= 240
        new_x %= 128    # smaller than the 135 window but needs to be divisible by 8
        if (new_x, new_y) in self.body or (new_x, new_y) in self.walls:
            self.die()
        else:
            if (new_x, new_y) == self.target:
                self.score += 1
                self.new_food()
                self.body = [(new_x, new_y)] + self.body
            else:
                tidal.display.fill_rect(self.body[-1][0], self.body[-1][1], 8, 8, tidal.BLACK)
                self.body = [(new_x, new_y)] + self.body[:-1]
            tidal.display.fill_rect(new_x, new_y, 8, 8, tidal.YELLOW)

    def on_deactivate(self):
        super().on_deactivate()
        self.timer_task.cancel()

    def update_score(self):
        tidal.display.fill_rect(0,232,135,16, tidal.BLACK)
        tidal.display.text(default_font, "   {:>5}       {}".format(self.score, self.lives), 0, 232)

    def die(self):
        self.lives -= 1
        if self.lives == 0:
            # print the game over screen
            tidal.display.fill(tidal.BLACK)
            tidal.display.text(default_font, "GAME", (135-32)//2, 92)
            tidal.display.text(default_font, "OVER", (135-32)//2, 100)

            tidal.display.text(default_font, f"Score: {self.score}", 25, 120)

            tidal.display.text(default_font, "Press Joystick", 10, 170)
            tidal.display.text(default_font, "to play again", 14, 178)
            self.timer_task.cancel()
            self.buttons.on_press(tidal.JOY_CENTRE, self.game_restart)
        else:
            self.level_restart()

    def new_food(self):
        while True:
            new_x = random.randrange(0,128,8)
            new_y = random.randrange(0,224,8)
            if (not (new_x, new_y) in self.walls) and (not (new_x, new_y) in self.body):
                break
        self.target = (new_x, new_y)
        tidal.display.fill_rect(new_x, new_y, 8, 8, tidal.GREEN)
        tidal.display.fill_rect(0, 0, 8, 8, tidal.RED)		# this doesn't do anything for some reason but if you remove it the line above doesn't do anything
        self.update_score()

    def game_restart(self):
        self.buttons.on_press(tidal.JOY_CENTRE, None)
        self.score = 0
        self.lives = 3
        self.level_restart()
        self.timer_task = self.periodic(100, self.update)

    def level_restart(self):
        self.direction = UP
        self.body = [(72,120), (72,128)]
        tidal.display.fill(tidal.BLACK)
        for b in self.body:
            tidal.display.fill_rect(b[0], b[1], 8, 8, tidal.YELLOW)
        
        self.walls = []
        for x in range(0,128,8):
            self.walls.append((x,0))
            self.walls.append((x,216))
        for y in range(0,224,8):
            self.walls.append((0,y))
            self.walls.append((120,y))
        
        for w in self.walls:
            tidal.display.fill_rect(w[0], w[1], 8, 8, tidal.RED)

        self.new_food()
        
        tidal.display.text(default_font, "   Score   Lives", 0, 224)
        tidal.display.text(default_font, "   {:>5}       {}".format(self.score, self.lives), 0, 232)
		
main = Snake