"""
don't forget the options like having to hide from enemys

controls need some work
"""
import os
import pygame
import random

import sys
sys.path.append(os.path.join("..","..")) 
import game

myPath = os.path.dirname(os.path.abspath(__file__))

game_credits = ["Music: Mouse Hunt by Jay Man www.ourmusicbox.com"]


class Maze(game.Game):

    MOVE_SPEED = 5

    NUMBER_OF_COLUMNS = 38
    NUMBER_OF_ROWS = 30

    BLOCK_SIZE_IN_PIXELS = 20
    PLAYER_SIZE_IN_PIXELS = 14

    X_OFFSET = (game.SCREEN_WIDTH / 2) - \
        (NUMBER_OF_COLUMNS * BLOCK_SIZE_IN_PIXELS) / 2
    Y_OFFSET = (game.SCREEN_HEIGHT / 2) - \
        (NUMBER_OF_ROWS * BLOCK_SIZE_IN_PIXELS) / 2

    class PD():

        def __init__(self, colorIndex):
            self.penguin = game.CharacterObject(
                colorIndex, Maze.PLAYER_SIZE_IN_PIXELS)

    def __init__(self, players, screen):
        game.Game.__init__(self, players, screen)

        self.bgColor = (0, 0, 0)
        self.white = (255, 255, 255)

        self.playersDetails = []

        for a in range(len(players)):
            t = Maze.PD(players[a].colorIndex)
            self.playersDetails.append(t)

        self.grid = [[0 for x in range(Maze.NUMBER_OF_COLUMNS)]
                     for y in range(Maze.NUMBER_OF_ROWS)]

        self.startingPositions = [[0, 0], [1, 0], [0, 1], [1, 1]]


        self.tune = os.path.join(myPath,"Mouse_Hunt.ogg")
        self.reset()

        game.initSmallerPenguins(Maze.PLAYER_SIZE_IN_PIXELS)

    def makeMaze(self, w, h):

        mx = w - 2
        my = h - 2

        dx = [0, 1, 0, -1]
        dy = [-1, 0, 1, 0]  # 4 directions to move in the maze
        maze = [[0 for x in range(mx)] for y in range(my)]
        stack = [(random.randint(0, mx - 1), random.randint(0, my - 1))]

        while len(stack) > 0:
            (cx, cy) = stack[-1]
            maze[cy][cx] = 1
            # find a new cell to add
            nlst = []  # list of available neighbors
            for i in range(4):
                nx = cx + dx[i]
                ny = cy + dy[i]
                if nx >= 0 and nx < mx and ny >= 0 and ny < my:
                    if maze[ny][nx] == 0:
                        # of occupied neighbors must be 1
                        ctr = 0
                        for j in range(4):
                            ex = nx + dx[j]
                            ey = ny + dy[j]
                            if ex >= 0 and ex < mx and ey >= 0 and ey < my:
                                if maze[ey][ex] == 1:
                                    ctr += 1
                        if ctr == 1:
                            nlst.append(i)
            # if 1 or more neighbors available then randomly select one and
            # move
            if len(nlst) > 0:
                ir = nlst[random.randint(0, len(nlst) - 1)]
                cx += dx[ir]
                cy += dy[ir]
                stack.append((cx, cy))
            else:
                stack.pop()

        for y in range(my):
            for x in range(mx):
                if maze[y][x] == 1:
                    self.grid[y + 1][x + 1] = 0
                else:
                    self.grid[y + 1][x + 1] = 1

        # make wall
        for x in range(Maze.NUMBER_OF_COLUMNS):
            self.grid[0][x] = 1
            self.grid[Maze.NUMBER_OF_ROWS - 1][x] = 1

        for y in range(Maze.NUMBER_OF_ROWS):
            self.grid[y][0] = 1
            self.grid[y][Maze.NUMBER_OF_COLUMNS - 1] = 1

        self.grid[Maze.NUMBER_OF_ROWS - 2][1] = 0
        self.grid[Maze.NUMBER_OF_ROWS - 2][2] = 0

        self.grid[Maze.NUMBER_OF_ROWS - 3][1] = 0
        self.grid[Maze.NUMBER_OF_ROWS - 3][2] = 0

        ey = random.randint(1, Maze.NUMBER_OF_ROWS - 2)

        self.grid[ey][Maze.NUMBER_OF_COLUMNS - 1] = 2

        # make sure the exit not blocked
        if ey != 1:
            self.grid[ey - 1][Maze.NUMBER_OF_COLUMNS - 2] = 0

        self.grid[ey][Maze.NUMBER_OF_COLUMNS - 2] = 0

        if ey < Maze.NUMBER_OF_ROWS - 1:
            self.grid[ey + 1][Maze.NUMBER_OF_COLUMNS - 2] = 0

    def reset(self):

        for ai, a in enumerate(self.playersDetails):
            a.alive = True
            a.penguin.rect.x = Maze.BLOCK_SIZE_IN_PIXELS + \
                (self.startingPositions[ai][0] * Maze.BLOCK_SIZE_IN_PIXELS)
            a.penguin.rect.y = (
                (Maze.NUMBER_OF_ROWS - 3) * Maze.BLOCK_SIZE_IN_PIXELS) + (
                Maze.BLOCK_SIZE_IN_PIXELS * self.startingPositions[ai][1])
            a.penguin.rect.w = Maze.PLAYER_SIZE_IN_PIXELS
            a.penguin.rect.h = Maze.PLAYER_SIZE_IN_PIXELS

        self.makeMaze(Maze.NUMBER_OF_COLUMNS, Maze.NUMBER_OF_ROWS)

    def checkPoint(self, x, y):
        x = int(x / Maze.BLOCK_SIZE_IN_PIXELS)
        y = int(y / Maze.BLOCK_SIZE_IN_PIXELS)

        # boundry
        if x < 0 or y < 0 or x > Maze.NUMBER_OF_COLUMNS or y > Maze.NUMBER_OF_ROWS:
            return 0

        return self.grid[y][x]

    def game_loop(self):

        self.screen.fill(self.bgColor)


        for y in range(Maze.NUMBER_OF_ROWS):
            for x in range(Maze.NUMBER_OF_COLUMNS):
                if self.grid[y][x] == 1:
                    pygame.draw.rect(self.screen,
                                     self.white,
                                     [Maze.X_OFFSET + x * Maze.BLOCK_SIZE_IN_PIXELS,
                                      Maze.Y_OFFSET + y * Maze.BLOCK_SIZE_IN_PIXELS,
                                      Maze.BLOCK_SIZE_IN_PIXELS,
                                      Maze.BLOCK_SIZE_IN_PIXELS])

        for pi, p in enumerate(self.playersDetails):

            con = self.players[pi]

            if p.alive:

                p.penguin.draw(self.screen, Maze.X_OFFSET, Maze.Y_OFFSET)

                if self.gameMode == game.Game.PLAYING:

                    newX = p.penguin.rect.x
                    newY = p.penguin.rect.y

                    if con.dirKeys[1]:
                        newX += Maze.MOVE_SPEED
                        p.penguin.direction = game.CharacterObject.RIGHT

                    if con.dirKeys[3]:
                        newX -= Maze.MOVE_SPEED
                        p.penguin.direction = game.CharacterObject.LEFT

                    if con.dirKeys[0]:
                        newY -= Maze.MOVE_SPEED
                        p.penguin.direction = game.CharacterObject.UP

                    if con.dirKeys[2]:
                        newY += Maze.MOVE_SPEED
                        p.penguin.direction = game.CharacterObject.DOWN

                    if self.checkPoint(newX, newY) != 1:
                        if self.checkPoint(
                                newX + Maze.PLAYER_SIZE_IN_PIXELS, newY) != 1:
                            if self.checkPoint(
                                    newX, newY + Maze.PLAYER_SIZE_IN_PIXELS) != 1:
                                if self.checkPoint(
                                        newX + Maze.PLAYER_SIZE_IN_PIXELS,
                                        newY + Maze.PLAYER_SIZE_IN_PIXELS) != 1:

                                    if p.penguin.rect.x != newX or p.penguin.rect.y != newY:
                                        p.penguin.rect.x = newX
                                        p.penguin.rect.y = newY
                                        p.penguin.updateAnimation()

                                    if self.checkPoint(
                                            p.penguin.rect.centerx, p.penguin.rect.centery) == 2:
                                        self.playerWon(pi)


def go_game(players, screen):
    return Maze(players, screen)


if __name__ == '__main__':
    game.moduleRun(go_game)
