from common import pygame, os, json, uuid, deepcopy, dataclass, field
import eb_objects
import eb_terrain
import eb_creatures

cell_classes = {"Ground": eb_terrain.Ground}
main_dir = os.path.dirname(os.path.abspath(__file__))
sprites_dir = os.path.join(main_dir, "res", "sprites") 
#file_path = os.path.join(main_dir, "res", "sprites", "grass_small.png")

def scale_image(image, n):
    orig_size = image.get_size()
    new_size = (int(orig_size[0] * n), int(orig_size[1] * n))
    return pygame.transform.scale(image, new_size)

@dataclass
class Cell:
    terrain_obj:  any
    #item_obj:     any
    #creature_obj: any
    is_target: bool = False

@dataclass
class Map:
    name:          str
    cells:         dict  = field(default_factory = dict)
    color:         str   = "gray57"
    target_color:  str   = "gold"
    size:          int   = 150
    bord:          int   = 5
    scale:         float = 1
    cam_x:         int   = 0
    cam_y:         int   = 0
    cell_dist:     int   = 2

    def __post_init__(self):
        self.cells = {}
        with open(self.name, 'r') as file:
            buff = json.load(file)
        for line in range(len(buff)):
            self.cells[line] = []
            for cell in buff[str(line)]:
                final_cell = Cell(cell_classes[cell["type"]](**cell["cell"]["terrain_obj"]))
                self.cells[line].append(deepcopy(final_cell))   

    def draw(self, screen, sprites, grid = True):
        for l in range(len(self.cells)):
            for i, cell in enumerate(self.cells[l]):
                x = int((i * self.size + self.cam_x) * self.scale)
                y = int((l * self.size + self.cam_y) * self.scale)
                w = int(self.size * self.scale - self.cell_dist)
                h = int(self.size * self.scale - self.cell_dist)
                
                #add if scale != prev_scale: no scale
                scaled = scale_image(sprites[cell.terrain_obj.sprite], self.scale)
                scaled_rect = scaled.get_rect(center = (x + w/2, y + h/2))
                screen.blit(scaled, scaled_rect)

                if grid:
                    pygame.draw.rect(screen, self.color, pygame.Rect(x, y, w, h), self.bord)
                
@dataclass
class Engine:
    sprites:      dict            = field(default_factory = dict)
    screen:       pygame.Surface  = ((1, 1))
    width:        int             = 1600
    height:       int             = 800
    camera_step:  int             = 10
    scale_step:   float           = 0.01
    
    def __post_init__(self):
        self.sprites = {}
        pygame.init()
        pygame.display.set_caption('Elvenbane')
        self.screen = pygame.display.set_mode((self.width, self.height))
        self.load_sprites()
                
    def load_sprites(self, folder_path = sprites_dir):
        for filename in os.listdir(folder_path):
            if filename.lower().endswith('.png'):
                name = os.path.splitext(filename)[0]
                self.sprites[name] = pygame.image.load(os.path.join(folder_path, filename)).convert_alpha()

    def main_loop(self):                
        clock = pygame.time.Clock()        
        running = True
        unlock = True
        easy_map = Map("def_map.json")
        #gr = pygame.image.load(file_path).convert_alpha()

        while running:
            # poll for events
            # pygame.QUIT event means the user clicked X to close your window
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False

            # fill the screen with a color to wipe away anything from last frame
            self.screen.fill("chartreuse4")

            easy_map.draw(self.screen, self.sprites)

            if unlock:
                keys = pygame.key.get_pressed()   
                if keys[pygame.K_w]:
                    easy_map.cam_y -= self.camera_step
                if keys[pygame.K_s]:
                    easy_map.cam_y += self.camera_step
                if keys[pygame.K_a]:
                    easy_map.cam_x -= self.camera_step
                if keys[pygame.K_d]:
                    easy_map.cam_x += self.camera_step
                if keys[pygame.K_q]:
                    easy_map.scale += self.scale_step
                if keys[pygame.K_e] and easy_map.scale >= self.scale_step:
                    easy_map.scale -= self.scale_step
                if keys[pygame.K_ESCAPE]:
                    running = False

            # flip() the display to put your work on screen
            pygame.display.flip()
            # limits FPS to 60
            clock.tick(60)

        pygame.quit()