import math
from typing import Tuple, Any

import aggdraw


def circle(draw: aggdraw.Draw, center: Tuple[float, float], radius: float, _: Any, pen: aggdraw.Pen, brush: aggdraw.Brush, **__: Any) -> None:
    """Draws a circle (angle doesn't change a circle's appearance)."""
    x, y = center
    draw.ellipse((x - radius, y - radius, x + radius, y + radius), pen, brush)


def square(draw: aggdraw.Draw, center: Tuple[float, float], radius: float, angle: float, pen: aggdraw.Pen, brush: aggdraw.Brush, **_: Any) -> None:
    """Draws a square rotated by the grid angle."""
    cx, cy = center
    rad = math.radians(angle)
    cos_a, sin_a = math.cos(rad), math.sin(rad)

    corners = [
        (-radius, -radius),
        (radius, -radius),
        (radius, radius),
        (-radius, radius)
    ]

    rotated_corners = []
    for px, py in corners:
        rx = px * cos_a - py * sin_a + cx
        ry = px * sin_a + py * cos_a + cy
        rotated_corners.extend([rx, ry])

    draw.polygon(rotated_corners, pen, brush)


def triangle(draw: aggdraw.Draw, center: Tuple[float, float], radius: float, angle: float, pen: aggdraw.Pen, brush: aggdraw.Brush, **_: Any) -> None:
    """Draws an equilateral triangle rotated by the grid angle."""
    cx, cy = center

    rad_offset = math.radians(angle) - (math.pi / 2)

    vertices = []

    for i in range(3):
        phi = rad_offset + (2 * math.pi / 3) * i
        vx = cx + radius * math.cos(phi)
        vy = cy + radius * math.sin(phi)
        vertices.extend([vx, vy])

    draw.polygon(vertices, pen, brush)


def polygon(draw: aggdraw.Draw, center: Tuple[float, float], radius: float, angle: float, pen: aggdraw.Pen, brush: aggdraw.Brush, sides: int = 5, **_: Any) -> None:
    """
    Draws a regular polygon with 'n' sides.
    - sides=3: Triangle
    - sides=4: Diamond/Square
    - sides=5: Pentagon
    - sides=6: Hexagon
    """
    cx, cy = center

    rad_offset = math.radians(angle) - (math.pi / 2)

    vertices = []
    for i in range(sides):
        phi = rad_offset + (2 * math.pi / sides) * i
        vx = cx + radius * math.cos(phi)
        vy = cy + radius * math.sin(phi)
        vertices.extend([vx, vy])

    draw.polygon(vertices, pen, brush)


def star(draw: aggdraw.Draw, center: Tuple[float, float], radius: float, angle: float, pen: aggdraw.Pen, brush: aggdraw.Brush, points: int = 5, inner_radius: float = None, **_: Any) -> None:
    """
    Draws a star with 'n' points.
    - points: Number of star tips
    - inner_radius: Distance to the 'valleys'. Defaults to half the radius.
    """
    cx, cy = center
    if inner_radius is None:
        inner_radius = radius * 0.5

    rad_offset = math.radians(angle) - (math.pi / 2)

    vertices = []

    for i in range(points * 2):
        r = radius if i % 2 == 0 else inner_radius

        phi = rad_offset + (math.pi / points) * i
        vx = cx + r * math.cos(phi)
        vy = cy + r * math.sin(phi)
        vertices.extend([vx, vy])

    draw.polygon(vertices, pen, brush)
