"""
Pipeline parameters - Runtime configuration layer for animation control.

PipelineParams is the target for AnimationController - animation events
modify these params, which the pipeline then applies to its stages.
"""

from dataclasses import dataclass, field
from typing import Any

try:
    from engine.display import BorderMode
except ImportError:
    BorderMode = object  # Fallback for type checking


@dataclass
class PipelineParams:
    """Runtime configuration for the pipeline.

    This is the canonical config object that AnimationController modifies.
    Stages read from these params to adjust their behavior.
    """

    # Source config
    source: str = "headlines"
    source_refresh_interval: float = 60.0

    # Display config
    display: str = "terminal"
    border: bool | BorderMode = False
    positioning: str = "mixed"  # Positioning mode: "absolute", "relative", "mixed"

    # Camera config
    camera_mode: str = "vertical"
    camera_speed: float = 1.0  # Default speed
    camera_x: int = 0  # For horizontal scrolling

    # Effect config
    effect_order: list[str] = field(
        default_factory=lambda: ["noise", "fade", "glitch", "firehose"]
    )
    effect_enabled: dict[str, bool] = field(default_factory=dict)
    effect_intensity: dict[str, float] = field(default_factory=dict)

    # Animation-driven state (set by AnimationController)
    pulse: float = 0.0
    current_effect: str | None = None
    path_progress: float = 0.0

    # Viewport
    viewport_width: int = 80
    viewport_height: int = 24

    # Firehose
    firehose_enabled: bool = False

    # Runtime state
    frame_number: int = 0
    fps: float = 60.0

    def get_effect_config(self, name: str) -> tuple[bool, float]:
        """Get (enabled, intensity) for an effect."""
        enabled = self.effect_enabled.get(name, True)
        intensity = self.effect_intensity.get(name, 1.0)
        return enabled, intensity

    def set_effect_config(self, name: str, enabled: bool, intensity: float) -> None:
        """Set effect configuration."""
        self.effect_enabled[name] = enabled
        self.effect_intensity[name] = intensity

    def is_effect_enabled(self, name: str) -> bool:
        """Check if an effect is enabled."""
        if name not in self.effect_enabled:
            return True  # Default to enabled
        return self.effect_enabled.get(name, True)

    def get_effect_intensity(self, name: str) -> float:
        """Get effect intensity (0.0 to 1.0)."""
        return self.effect_intensity.get(name, 1.0)

    def to_dict(self) -> dict[str, Any]:
        """Convert to dictionary for serialization."""
        return {
            "source": self.source,
            "display": self.display,
            "positioning": self.positioning,
            "camera_mode": self.camera_mode,
            "camera_speed": self.camera_speed,
            "effect_order": self.effect_order,
            "effect_enabled": self.effect_enabled.copy(),
            "effect_intensity": self.effect_intensity.copy(),
            "pulse": self.pulse,
            "current_effect": self.current_effect,
            "viewport_width": self.viewport_width,
            "viewport_height": self.viewport_height,
            "firehose_enabled": self.firehose_enabled,
        }

    @classmethod
    def from_dict(cls, data: dict[str, Any]) -> "PipelineParams":
        """Create from dictionary."""
        params = cls()
        for key, value in data.items():
            if hasattr(params, key):
                setattr(params, key, value)
        return params

    def copy(self) -> "PipelineParams":
        """Create a copy of this params object."""
        params = PipelineParams()
        params.source = self.source
        params.display = self.display
        params.camera_mode = self.camera_mode
        params.camera_speed = self.camera_speed
        params.camera_x = self.camera_x
        params.effect_order = self.effect_order.copy()
        params.effect_enabled = self.effect_enabled.copy()
        params.effect_intensity = self.effect_intensity.copy()
        params.pulse = self.pulse
        params.current_effect = self.current_effect
        params.path_progress = self.path_progress
        params.viewport_width = self.viewport_width
        params.viewport_height = self.viewport_height
        params.firehose_enabled = self.firehose_enabled
        params.frame_number = self.frame_number
        params.fps = self.fps
        return params


# Default params for different modes
DEFAULT_HEADLINE_PARAMS = PipelineParams(
    source="headlines",
    display="terminal",
    camera_mode="vertical",
    effect_order=["noise", "fade", "glitch", "firehose"],
)

DEFAULT_PYGAME_PARAMS = PipelineParams(
    source="headlines",
    display="pygame",
    camera_mode="vertical",
    effect_order=["noise", "fade", "glitch", "firehose"],
)

DEFAULT_PIPELINE_PARAMS = PipelineParams(
    source="pipeline",
    display="pygame",
    camera_mode="trace",
    effect_order=[],  # No effects for pipeline viz
)
