"""
Tile, Star, and Map classes for hexagon-grid rendering.
"""
import math


class Tile:
    """
    Represents a single tile in a grid.
    Attributes:
        x (int): Column index of the tile.
        y (int): Row index of the tile.
        content (list): List of content items in this tile.
    """
    def __init__(self, x, y, content=None):
        self.x = x
        self.y = y
        self.content = content or []


class Star:
    """
    A star located on a specific tile.

    Attributes:
        type (str): One of the allowed star types.
        location (Tile): The Tile instance where the star resides.
    """
    ALLOWED_TYPES = (
        "yellow dwarf",
        "red dwarf",
        "blue giant",
        "red giant",
        "yellow gigant",
    )
    # circle color per star type
    STAR_COLORS = {
        "yellow dwarf": "#FFFF00",
        "red dwarf":    "#FF0000",
        "blue giant":   "#0000FF",
        "red giant":    "#FF4500",
        "yellow gigant":"#FFD700",
    }
    # relative circle radius scale: dwarfs smaller, giants larger
    DWARF_SCALE = 0.2
    GIANT_SCALE = 0.5

    def __init__(self, star_type, location):
        if star_type not in Star.ALLOWED_TYPES:
            raise ValueError(f"Invalid star type: {star_type!r}")
        if not isinstance(location, Tile):
            raise TypeError("location must be a Tile instance")
        self.type = star_type
        self.location = location


class Map:
    """
    A hexagon-tiled map of arbitrary size.
    Attributes:
        rows (int): Number of rows.
        cols (int): Number of columns.
        tile_size (float): Size (radius) of each hexagon.
        tiles (dict): Mapping of (x, y) => Tile objects.
    """
    def __init__(self, rows, cols, tile_size=50):
        self.rows = rows
        self.cols = cols
        self.tile_size = tile_size
        self.tiles = {}
        for y in range(rows):
            for x in range(cols):
                self.tiles[(x, y)] = Tile(x, y)

    def render(self):
        """
        Returns an HTML (SVG) string representing the hexagonal grid.
        """
        S = self.tile_size
        h = math.sqrt(3) * S
        verts = [
            (S, 0),
            (3 * S, 0),
            (4 * S, h),
            (3 * S, 2 * h),
            (S, 2 * h),
            (0, h),
        ]
        width = S * (3 * self.cols + 1)
        height = h * (2 * self.rows + 1)
        parts = [
            f'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {width} {height}">'
        ]
        for (x, y), tile in self.tiles.items():
            dx = x * 3 * S
            dy = (x % 2) * h + y * 2 * h
            pts = " ".join(f"{dx+vx},{dy+vy}" for vx, vy in verts)
            # draw tile background as black
            parts.append(
                f'<polygon points="{pts}" fill="#000" stroke="#333" stroke-width="2"/>'
            )
            # render star if present on this tile
            star = getattr(tile, 'star', None)
            if star is not None:
                cx = dx + 2 * S
                cy = dy + h
                # choose scale based on star type
                scale = (Star.DWARF_SCALE if 'dwarf' in star.type
                         else Star.GIANT_SCALE)
                r = S * scale
                color = Star.STAR_COLORS.get(star.type, '#FFF')
                # include title for tooltip
                parts.append(
                    f'<circle cx="{cx}" cy="{cy}" r="{r}" fill="{color}">'
                    f'<title>{star.name}</title>'
                    f'</circle>'
                )
        parts.append("</svg>")
        return "\n".join(parts)