"""Module for performing tutte embeddings"""
import math
from typing import Any

import numpy as np
from sage.all import Graph  # type: ignore


def tutte_embedding(g: Graph, outer: list[Any]) -> dict[Any, tuple[float, float]]:
    """Compute a Tutte embedding fixing outer on a convex polygon, solving for inner vertices."""

    outer_set = set(outer)
    inner = [v for v in g.vertices() if v not in outer_set]

    pos: dict[Any, tuple[float, float]] = {}
    for i, v in enumerate(outer):
        angle = 2 * math.pi * i / len(outer)
        pos[v] = (math.cos(angle), math.sin(angle))

    if not inner:
        return pos

    inner_idx = {v: i for i, v in enumerate(inner)}
    n = len(inner)
    A = np.zeros((n, n))
    bx = np.zeros(n)
    by = np.zeros(n)

    for i, v in enumerate(inner):
        neighbors = g.neighbors(v)
        deg = len(neighbors)
        A[i, i] = 1.0
        for w in neighbors:
            if w in inner_idx:
                A[i, inner_idx[w]] = -1.0 / deg
            else:
                bx[i] += pos[w][0] / deg
                by[i] += pos[w][1] / deg

    x = np.linalg.solve(A, bx)
    y = np.linalg.solve(A, by)
    for i, v in enumerate(inner):
        pos[v] = (float(x[i]), float(y[i]))

    return pos
