# Import modules
from pygame.locals import *
import pygame
import json

# PROGRAM UMÍ ČÍST POUZE JSON DATA

def main():  # Main function
    filename = "_porota/json/POROTA_Level_6_Distance_16_or_Energy_34.json"  # Path to json file

    with open(filename, "r") as f:
        data_store = json.load(f)  # Load json file

    clock = pygame.time.Clock()

    # Define colors
    black = (0, 0, 0)
    white = (255, 255, 255)

    class Player:  # Class player
        x = data_store["START"]["X"] * 32-32
        y = data_store["START"]["Y"] * 32-32
        speed = 32
        energy = int(data_store["START"]["E"])

        def moveRight(self, safe):  # Movement to the right
            if self.bonus(x=self.x + self.speed, safe=safe):
                Maze.maze[self.y // 32 * data_store["SIRKA"] + self.x // 32] = "K"
                self.x = self.x + self.speed
                if self.energy <= 0:
                    self.energy = 0
                    App.gameover = True

        def moveLeft(self, safe):  # Movement to the left
            if self.bonus(x=self.x - self.speed, safe=safe):
                Maze.maze[self.y // 32 * data_store["SIRKA"] + self.x // 32] = "K"
                self.x = self.x - self.speed
                if self.energy <= 0:
                    self.energy = 0
                    App.gameover = True

        def moveUp(self, safe):  # Movement to the up
            if self.bonus(y=self.y - self.speed, safe=safe):
                Maze.maze[self.y // 32 * data_store["SIRKA"] + self.x // 32] = "K"
                self.y = self.y - self.speed
                if self.energy <= 0:
                    self.energy = 0
                    App.gameover = True

        def moveDown(self, safe):  # Movement to the down
            if self.bonus(y=self.y + self.speed, safe=safe):
                Maze.maze[self.y // 32 * data_store["SIRKA"] + self.x // 32] = "K"
                self.y = self.y + self.speed

                if self.energy <= 0:
                    self.energy = 0
                    App.gameover = True

        def bonus(self, x=None, y=None, safe=None):  # Control, destroy blocks, ...
            if x is None:
                x = self.x

            if y is None:
                y = self.y

            if x < 0 or y < 0:
                return False

            try:
                if Maze.maze[y//32*data_store["SIRKA"]+x//32] == "V" or Maze.maze[y//32*data_store["SIRKA"]+x//32] == "K":  # When entity is Empty (free space)
                    if x//32 <= data_store["SIRKA"]-1:
                        self.energy = self.energy - 1
                        Maze.maze[y // 32 * data_store["SIRKA"] + x // 32] = "K"
                        return True

                elif "J" in Maze.maze[y//32*data_store["SIRKA"]+x//32]:  # When entity is food
                    self.energy = self.energy + int(Maze.maze[y//32*data_store["SIRKA"]+x//32][1])

                    self.energy = self.energy - 1
                    return True

                elif "Z" in Maze.maze[y//32*data_store["SIRKA"]+x//32]:  # When entity is wall
                    self.energy = self.energy - int(Maze.maze[y//32*data_store["SIRKA"]+x//32][1])
                    Maze.maze[y//32*data_store["SIRKA"]+x//32] = "K"
                    self.energy = self.energy - 1
                    return True

                elif "B" in Maze.maze[y//32*data_store["SIRKA"]+x//32]:
                    try:

                        self.energy = self.energy - int(Maze.maze[y//32*data_store["SIRKA"]+x//32][1])
                        Maze.maze[y // 32 * data_store["SIRKA"] + x // 32] = "K"
                        self.energy = self.energy - 1
                        return True

                    except:
                        if safe is not True:  # When is active safe mode
                            self.energy = 0
                            return True

                        else:
                            return False

                elif "C" in Maze.maze[y//32*data_store["SIRKA"]+x//32]:
                    Maze.maze[y//32*data_store["SIRKA"]+x//32] = "V"
                    self.energy = self.energy - 1
                    App.win = True
                    return True

            except:
                return False

    class Maze:  # Class to generate maze
        maze = ",".join(data_store["PLAN"]).split(",")
        maze[(data_store["CIL"]["Y"]-1)*data_store["SIRKA"]+data_store["CIL"]["X"]-1] = "C"

        def __init__(self):
            self.M = data_store["SIRKA"]
            self.N = data_store["VYSKA"]

        def draw(self, display_surf, wall, food, bomb, finish, hist):
            bx = 0
            by = 0
            for i in range(0, self.M * self.N):
                if "Z" in self.maze[bx + (by * self.M)]:
                    display_surf.blit(wall, (bx * 32, by * 32))

                    if self.maze[bx + (by * self.M)].split("Z")[1]:
                        font = pygame.font.Font('freesansbold.ttf', 22)
                        text = font.render(self.maze[bx + (by * self.M)].split("Z")[1], True, white)
                        textRect = text.get_rect()
                        textRect.center = (bx*32+16, by*32+16)
                        display_surf.blit(text, textRect)

                if "J" in self.maze[bx + (by * self.M)]:
                    display_surf.blit(food, (bx * 32, by * 32))

                    if self.maze[bx + (by * self.M)].split("J")[1]:
                        font = pygame.font.Font('freesansbold.ttf', 22)
                        text = font.render(self.maze[bx + (by * self.M)].split("J")[1], True, black)
                        textRect = text.get_rect()
                        textRect.center = (bx*32+16, by*32+16)
                        display_surf.blit(text, textRect)

                if "B" in self.maze[bx + (by * self.M)]:
                    display_surf.blit(bomb, (bx * 32, by * 32))

                    if self.maze[bx + (by * self.M)].split("B")[1]:
                        font = pygame.font.Font('freesansbold.ttf', 22)
                        text = font.render(self.maze[bx + (by * self.M)].split("B")[1], True, white)
                        textRect = text.get_rect()
                        textRect.center = (bx*32+16, by*32+16)
                        display_surf.blit(text, textRect)

                if "C" in self.maze[bx + (by * self.M)]:
                    display_surf.blit(finish, (bx * 32, by * 32))

                if "K" in self.maze[bx + (by * self.M)]:
                    display_surf.blit(hist, (bx * 32, by * 32))

                bx = bx + 1
                if bx > self.M - 1:
                    bx = 0
                    by = by + 1

    class App:  # Main app
        windowWidth = 800
        windowHeight = 600
        player = 0
        gameover = False
        win = False
        stop = False

        def __init__(self):
            self._running = True
            self.display = None
            self._image_surf = None
            self.wall = None
            self.finish = None
            self.bomb = None
            self.food = None
            self.hist = None
            self.safe = False
            self.player = Player()
            self.maze = Maze()
            self.player_time = pygame.time.get_ticks()

        def on_init(self):
            pygame.init()
            self.display = pygame.display.set_mode((self.windowWidth, self.windowHeight), pygame.HWSURFACE)
            pygame.display.set_caption("Packman")
            self._running = True
            self._image_surf = pygame.image.load("img/pellet32.png").convert()
            self.wall = pygame.image.load("img/wall32.png").convert()
            self.finish = pygame.image.load("img/finish32.png").convert()
            self.food = pygame.image.load("img/cake32.png").convert()
            self.bomb = pygame.image.load("img/bomb32.png").convert()
            self.hist = pygame.image.load("img/hist32.png").convert()

        def on_event(self, event):
            if event.type == QUIT:
                self._running = False

        def on_render(self):
            self.display.fill((0, 0, 0))

            self.maze.draw(self.display, self.wall, self.food, self.bomb, self.finish, self.hist)
            self.display.blit(self._image_surf, (self.player.x, self.player.y))

            # Titles
            font = pygame.font.Font('freesansbold.ttf', 20)
            text = font.render("Energie: " + str(self.player.energy), True, white)
            textRect = text.get_rect()
            textRect.left = 500
            textRect.top = 30
            self.display.blit(text, textRect)

            font = pygame.font.Font('freesansbold.ttf', 20)
            text = font.render("Exit - Esc", True, white)
            textRect = text.get_rect()
            textRect.left = 500
            textRect.top = 100
            self.display.blit(text, textRect)

            font = pygame.font.Font('freesansbold.ttf', 20)
            text = font.render("Reset - r", True, white)
            textRect = text.get_rect()
            textRect.left = 500
            textRect.top = 120
            self.display.blit(text, textRect)

            font = pygame.font.Font('freesansbold.ttf', 20)
            text = font.render("Move by darts (->; <-; ...)", True, white)
            textRect = text.get_rect()
            textRect.left = 500
            textRect.top = 140
            self.display.blit(text, textRect)

            if self.safe:  # When is active safe mode
                font = pygame.font.Font('freesansbold.ttf', 20)
                text = font.render("Safe mod (s): True", True, white)
                textRect = text.get_rect()
                textRect.left = 500
                textRect.top = 50
                self.display.blit(text, textRect)

            else:
                font = pygame.font.Font('freesansbold.ttf', 20)
                text = font.render("Safe mod (s): False", True, white)
                textRect = text.get_rect()
                textRect.left = 500
                textRect.top = 50
                self.display.blit(text, textRect)

            if self.gameover:  # When is game over
                font = pygame.font.Font('freesansbold.ttf', 22)
                text = font.render("Game over", True, white)
                textRect = text.get_rect()
                textRect.center = (400, 300)
                self.display.blit(text, textRect)
                self.stop = True

            if self.win:  # When is player winner
                font = pygame.font.Font('freesansbold.ttf', 22)
                text = font.render("You are winner!", True, white)
                textRect = text.get_rect()
                textRect.center = (400, 300)
                self.display.blit(text, textRect)
                self.stop = True

            pygame.display.flip()

        def on_cleanup(self):
            pygame.quit()

        def reset(self):
            main()

        def on_execute(self):
            clock.tick(20)  # Define speed

            if self.on_init() is False:
                self._running = False

            while self._running:
                pygame.event.pump()
                keys = pygame.key.get_pressed()

                if self.stop is False:
                    if pygame.time.get_ticks() - self.player_time >= 100:
                        self.player_time = pygame.time.get_ticks()

                        # Movement
                        if keys[K_RIGHT]:
                            self.player.moveRight(self.safe)

                        if keys[K_LEFT]:
                            self.player.moveLeft(self.safe)

                        if keys[K_UP]:
                            self.player.moveUp(self.safe)

                        if keys[K_DOWN]:
                            self.player.moveDown(self.safe)

                        if keys[K_s]:
                            if self.safe is True:
                                self.safe = False

                            else:
                                self.safe = True

                if keys[K_ESCAPE]:  # End program
                    self._running = False

                if keys[K_r]:  # Reset program
                    self.reset()

                self.on_render()
            self.on_cleanup()

    app = App()
    app.on_execute()


main()

