from collections import deque
class IsometricGeometry:
    CELL_PADDING_X = 1
    def calculate_coordinates(self, event):
        if self.input_lock:
            return
        # Get the mouse coordinates
        mouse_x = event.x
        mouse_y = event.y
        iso_x, iso_y = self.inv_iso_transform(mouse_x, mouse_y)
        self.cell_selected = (iso_x, iso_y)
        

    def get_direction(self, initial_coord, surrounding_coord):
        # Calcola la differenza tra le coordinate
        delta_x = surrounding_coord[0] - initial_coord[0]
        delta_y = surrounding_coord[1] - initial_coord[1]

        # Determina la direzione basandosi sulla differenza
        if delta_x == -1 and delta_y == 1:
            return 2  # Sud-Ovest
        elif delta_x == -1 and delta_y == 0:
            return 3  # Ovest
        elif delta_x == -1 and delta_y == -1:
            return 4  # Nord-Ovest
        elif delta_x == 0 and delta_y == -1:
            return 5  # Nord
        elif delta_x == 1 and delta_y == -1:
            return 6  # Nord-Est
        elif delta_x == 1 and delta_y == 0:
            return 7  # Est
        elif delta_x == 1 and delta_y == 1:
            return 8  # Sud-Est
        elif delta_x == 0 and delta_y == 1:
            return 1  # Sud
        else:
            return 1
    
    def find_neighbors(self, coordinates):
        """
        Find and return the cells adjacent to the cell at position (coordinates).

        Adjacent cells are those directly above, below, left, right,
        and all four diagonally adjacent cells.
        """
        neighbors = []
        x_coord, y_coord = coordinates

        # Check all eight possible directions
        for delta_x in [-1, 0, 1]:
            for delta_y in [-1, 0, 1]:
                new_x, new_y = x_coord + delta_x, y_coord + delta_y

                # Skip the cell itself
                if delta_x == 0 and delta_y == 0:
                    continue
                # Check if the new coordinates are within the battlefield
                if 0 <= new_x < self.width and 0 <= new_y < self.height:
                        neighbors.append((new_x, new_y))

        return neighbors
    
    def get_closest_neighbor(self, neighbors_list, target_position):
        """
        Find and return the neighbor cell in the neighbors_list closest to the target position.
        """
        # If there are no neighbors, return None
        if not neighbors_list:
            return None

        # Calculate the distance between the target position and each neighbor
        distances = [abs(((neighbor[0] - target_position[0])**2 + (neighbor[1] - target_position[1])**2)**0.5) for neighbor in neighbors_list]

        # Find the index of the smallest distance
        min_distance_index = distances.index(min(distances))

        # Return the neighbor corresponding to the smallest distance
        return neighbors_list[min_distance_index]
    
    def iso_transform(self, x, y):
        screen_x = (x - y) * self.cell_size // 2 + self.view_offset_x
        screen_y = (x + y) * self.cell_size // 4 + self.view_offset_y
        return screen_x, screen_y
    
    def inv_iso_transform(self, screen_x, screen_y):
        x = (2 * screen_y + screen_x - 2 * self.view_offset_x) // self.cell_size - 1
        y = (2 * screen_y - screen_x + 2 * self.view_offset_x) // self.cell_size
        return x, y

    def get_distance(self, position1, position2):
        x1, y1 = position1
        x2, y2 = position2
        return abs(((x2 - x1) ** 2 + (y2 - y1) ** 2) ** 0.5)
    def get_distance_components(self, position1, position2):
        x1, y1 = position1
        x2, y2 = position2
        return abs(x2 - x1), abs(y2 - y1)
    #function to check if a cell is near a wall
    def near_wall(self, position):
        x, y = position
        neighbors = self.find_neighbors(position)
        for neighbor in neighbors:
            if not self.battlefield[neighbor[1]][neighbor[0]].walkable:
                return True
    def min_steps_to_target(self, start, target):
        grid = [[0 for _ in range(self.width)] for _ in range(self.height)]
        rows, cols = len(grid), len(grid[0])
        dx = [0, 1, 0, -1]
        dy = [1, 0, -1, 0]
        queue = deque([start])
        visited = set([start])

        steps = 0
        while queue:
            for _ in range(len(queue)):
                x, y = queue.popleft()
                if (x, y) == target:
                    return steps

                for i in range(4):
                    nx, ny = x + dx[i], y + dy[i]
                    if 0 <= nx < rows and 0 <= ny < cols and (nx, ny) not in visited:
                        queue.append((nx, ny))
                        visited.add((nx, ny))
            steps += 1

        return -1      