"""
types.py
--------
Shared type definitions for the knot_animation package.

KnotConfig is the typed dictionary that flows between:
  KnotItem.to_dict()  →  knot_frame_handler  →  _make_torus_knot
  and the material / blend system.

All keys are optional (total=False) so callers can provide only the
relevant subset; consumers must use .get() with a sensible default.
"""
from __future__ import annotations

try:
    from typing import TypedDict
except ImportError:  # Python < 3.8
    from typing_extensions import TypedDict  # type: ignore[no-redef]


class KnotConfig(TypedDict, total=False):
    # ── Shape Type ───────────────────────────────────────────────────────────
    shape_type: str  # 'TORUS_KNOT' | 'MOBIUS' | 'LISSAJOUS' | 'SPIRAL'

    # ── Topology (Torus Knot) ────────────────────────────────────────────────
    torus_p: int
    mod_torus_p: float
    torus_q: int
    mod_torus_q: float
    flip_p: bool
    flip_q: bool
    multiple_links: bool

    # ── Topology (Mobius) ────────────────────────────────────────────────────
    mobius_twists: int
    mod_mobius_twists: float
    mobius_width: float
    mod_mobius_width: float

    # ── Topology (Lissajous 3D) ──────────────────────────────────────────────
    liss_kx: int
    mod_liss_kx: float
    liss_ky: int
    mod_liss_ky: float
    liss_kz: int
    mod_liss_kz: float
    liss_amp: float
    mod_liss_amp: float

    # ── Topology (Spherical Spiral) ──────────────────────────────────────────
    spiral_turns: int
    mod_spiral_turns: float
    spiral_R: float
    mod_spiral_R: float

    # ── Radii (Major/Minor mode) ──────────────────────────────────────────────
    torus_R: float
    mod_torus_R: float
    torus_r: float
    mod_torus_r: float

    # ── Radii (Ext/Int mode) ─────────────────────────────────────────────────
    mode: str        # 'MAJOR_MINOR' | 'EXT_INT'
    torus_eR: float
    mod_torus_eR: float
    torus_iR: float
    mod_torus_iR: float

    # ── Multipliers & phases ──────────────────────────────────────────────────
    torus_u: int
    torus_v: int
    torus_rP: float
    torus_sP: float
    torus_h: float
    mod_torus_h: float

    # ── Per-knot animation rates ──────────────────────────────────────────────
    spin_phase_rate: float
    rev_phase_rate: float
    height_rate: float
    scale_rate: float
    scale_amplitude: float
    cycle_rate: float

    # ── Geometry ──────────────────────────────────────────────────────────────
    geo_extrude: float
    mod_geo_extrude: float
    geo_offset: float
    mod_geo_offset: float
    geo_bDepth: float
    mod_geo_bDepth: float

    # ── Transition ────────────────────────────────────────────────────────────
    transition_frames: int
    transition_easing: str   # 'LINEAR' | 'QUAD_IN_OUT' | 'SMOOTHSTEP'

    # ── Legacy TKP colour path ────────────────────────────────────────────────
    use_colors: bool
    colorSet: str
    random_colors: bool

    # ── Material ──────────────────────────────────────────────────────────────
    material_mode: str       # 'PRESET' | 'PROJECT'
    shader_id: str
    preset_color: tuple
    preset_roughness: float
    preset_metallic: float
    preset_emission_strength: float
    uid: str

    # ── Private handler-injected keys (not stored in KnotItem) ───────────────
    _skip_material: bool     # tells _make_torus_knot to skip material assignment
    _scale_override: float   # per-frame scale multiplier computed by the handler
