"""Afterimage effect using previous frame."""

from engine.effects.types import EffectConfig, EffectContext, EffectPlugin


class AfterimageEffect(EffectPlugin):
    """Show a faint ghost of the previous frame.

    This effect requires a FrameBufferStage to be present in the pipeline.
    It shows a dimmed version of the previous frame super-imposed on the
    current frame.

    Attributes:
        name: "afterimage"
        config: EffectConfig with intensity parameter (0.0-1.0)
        param_bindings: Optional sensor bindings for intensity modulation

    Example:
        >>> effect = AfterimageEffect()
        >>> effect.configure(EffectConfig(intensity=0.3))
        >>> result = effect.process(buffer, ctx)
    """

    name = "afterimage"
    config: EffectConfig = EffectConfig(enabled=True, intensity=0.3)
    param_bindings: dict[str, dict[str, str | float]] = {}
    supports_partial_updates = False

    def process(self, buf: list[str], ctx: EffectContext) -> list[str]:
        """Apply afterimage effect using the previous frame.

        Args:
            buf: Current text buffer (list of strings)
            ctx: Effect context with access to framebuffer history

        Returns:
            Buffer with ghost of previous frame overlaid
        """
        if not buf:
            return buf

        # Get framebuffer history from context
        history = None

        for key in ctx.state:
            if key.startswith("framebuffer.") and key.endswith(".history"):
                history = ctx.state[key]
                break

        if not history or len(history) < 1:
            # No previous frame available
            return buf

        # Get intensity from config
        intensity = self.config.params.get("intensity", self.config.intensity)
        intensity = max(0.0, min(1.0, intensity))

        if intensity <= 0.0:
            return buf

        # Get the previous frame (index 1, since index 0 is current)
        prev_frame = history[1] if len(history) > 1 else None
        if not prev_frame:
            return buf

        # Blend current and previous frames
        viewport_height = ctx.terminal_height - ctx.ticker_height
        result = []

        for row in range(len(buf)):
            if row >= viewport_height:
                result.append(buf[row])
                continue

            current_line = buf[row]
            prev_line = prev_frame[row] if row < len(prev_frame) else ""

            if not prev_line:
                result.append(current_line)
                continue

            # Apply dimming effect by reducing ANSI color intensity or adding transparency
            # For a simple text version, we'll use a blend strategy
            blended = self._blend_lines(current_line, prev_line, intensity)
            result.append(blended)

        return result

    def _blend_lines(self, current: str, previous: str, intensity: float) -> str:
        """Blend current and previous line with given intensity.

        For text with ANSI codes, true blending is complex. This is a simplified
        version that uses color averaging when possible.

        A more sophisticated implementation would:
        1. Parse ANSI color codes from both lines
        2. Blend RGB values based on intensity
        3. Reconstruct the line with blended colors

        For now, we'll use a heuristic: if lines are similar, return current.
        If they differ, we alternate or use the previous as a faint overlay.
        """
        if current == previous:
            return current

        # Simple blending: intensity determines mix
        # intensity=1.0 => fully current
        # intensity=0.3 => 70% previous ghost, 30% current

        if intensity > 0.7:
            return current
        elif intensity < 0.3:
            # Show previous but dimmed (simulate by adding faint color/gray)
            return previous  # Would need to dim ANSI colors
        else:
            # For medium intensity, alternate based on character pattern
            # This is a placeholder for proper blending
            return current

    def configure(self, config: EffectConfig) -> None:
        """Configure the effect."""
        self.config = config
