import buttons
import display
import leds
import color
import utime
import urandom


BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)

UP = 0
RIGHT = 1
DOWN = 2
LEFT = 3


class Game:
    def __init__(self):
        self.disp = display.open()
        self.just_pressed = False
        self.head = (10, 30)
        self.body = [self.head]
        self.direction = RIGHT
        self.length = 5
        self.fruit = self.random_position()
        self.score = 0
        self.loop()

    def loop(self):
        running = True
        while running:
            self.handle_buttons()
            running = self.tick()
            self.render()
            utime.sleep(0.1)
        self.game_over()

    def render(self):
        self.disp.clear()
        self.disp.pixel(*self.head, col=RED)
        for pos in self.body:
            self.disp.pixel(*pos, col=WHITE)

        f_x, f_y = self.fruit
        self.disp.pixel(f_x, f_y, col=GREEN)
        self.disp.pixel(f_x - 1, f_y - 1, col=GREEN)
        self.disp.pixel(f_x - 1, f_y + 1, col=GREEN)
        self.disp.pixel(f_x + 1, f_y - 1, col=GREEN)
        self.disp.pixel(f_x + 1, f_y + 1, col=GREEN)
        self.disp.update()

    def tick(self):
        self.body = self.body[(self.length * -1):]
        x, y = self.head

        if self.direction == UP:
            y -= 1
        if self.direction == RIGHT:
            x += 1
        if self.direction == DOWN:
            y += 1
        if self.direction == LEFT:
            x -= 1

        self.head = (self.wrap_around(x, 160), self.wrap_around(y, 80))
        if self.head in self.body:
            return False
        if self.head == self.fruit:
            self.eat_fruit()

        self.body.append(self.head)
        return True


    def handle_buttons(self):
        pressed = buttons.read(buttons.BOTTOM_LEFT | buttons.BOTTOM_RIGHT)
        if pressed == 0:
            self.just_pressed = False
            return
        # Work around the fact that some button presses
        # are long enough to be registered twice.
        if self.just_pressed:
            return
        self.just_pressed = True

        if pressed & buttons.BOTTOM_LEFT != 0:
            if self.direction == UP:
                self.direction = LEFT
            else:
                self.direction -= 1

        elif pressed & buttons.BOTTOM_RIGHT != 0:
            if self.direction == LEFT:
                self.direction = UP
            else:
                self.direction += 1

    def eat_fruit(self):
        self.score += 1
        self.length += (3 * self.score)
        self.fruit = self.random_position()

    def game_over(self):
        self.disp.clear()
        self.disp.print("Game Over!\n  score: %d" % self.score, fg=RED)
        self.disp.update()

    def wrap_around(self, value, max_value):
        if value < 0:
            return max_value
        elif value > max_value:
            return 0
        else:
            return value

    def random_position(self):
        return (urandom.randint(1, 160 - 1),
                urandom.randint(1, 80 - 1))

game = Game()