"""L8 ELECTROMAGNETIC Layer

Force dynamics and polarity.
"""
from __future__ import annotations

from typing import List, Optional
import math

from .base import Layer, LayerID, Token
from .._core import PRIME_131


class L8_Electromagnetic(Layer):
    """L8 ELECTROMAGNETIC: Force dynamics and polarity."""

    LAYER_ID = LayerID.ELECTROMAGNETIC
    LAYER_NAME = "ELECTROMAGNETIC"
    LAYER_DESCRIPTION = "Force dynamics and polarity"

    def query(self, pattern: str, limit: int = 100) -> List[Token]:
        """Query by electromagnetic pattern."""
        pattern = pattern.lower()

        if pattern == "positive":
            # Positive polarity: basin < 65
            return [t for t in self._memory._tokens.values()
                    if t.basin < PRIME_131 // 2][:limit]
        elif pattern == "negative":
            # Negative polarity: basin >= 65
            return [t for t in self._memory._tokens.values()
                    if t.basin >= PRIME_131 // 2][:limit]
        elif pattern == "neutral":
            # Near center (basin 60-70)
            return [t for t in self._memory._tokens.values()
                    if 60 <= t.basin <= 70][:limit]

        return list(self._memory._tokens.values())[:limit]

    def filter(self, tokens: List[Token], **criteria) -> List[Token]:
        """Filter by electromagnetic criteria."""
        results = tokens

        if "polarity" in criteria:
            pol = criteria["polarity"]
            if pol == "positive":
                results = [t for t in results if t.basin < PRIME_131 // 2]
            elif pol == "negative":
                results = [t for t in results if t.basin >= PRIME_131 // 2]

        if "min_field" in criteria:
            min_f = criteria["min_field"]
            results = [t for t in results if self._field_strength(t) >= min_f]

        return results

    def _field_strength(self, token: Token) -> float:
        """Compute field strength from distance to center."""
        center = PRIME_131 // 2
        distance = abs(token.basin - center)
        return 1.0 - (distance / center)

    def navigate(self, token: Token, direction: str) -> Optional[Token]:
        """Navigate by electromagnetic direction."""
        if direction == "attract":
            # Find opposite polarity
            if token.basin < PRIME_131 // 2:
                candidates = [t for t in self._memory._tokens.values()
                             if t.basin >= PRIME_131 // 2]
            else:
                candidates = [t for t in self._memory._tokens.values()
                             if t.basin < PRIME_131 // 2]
            return candidates[0] if candidates else None
        elif direction == "repel":
            # Find same polarity, further away
            if token.basin < PRIME_131 // 2:
                candidates = [t for t in self._memory._tokens.values()
                             if t.basin < token.basin]
            else:
                candidates = [t for t in self._memory._tokens.values()
                             if t.basin > token.basin]
            return candidates[-1] if candidates else None
        return None

    def distance(self, a: Token, b: Token) -> float:
        """Electromagnetic distance: field interaction."""
        field_a = self._field_strength(a)
        field_b = self._field_strength(b)
        polarity_match = 1.0 if (a.basin < 65) == (b.basin < 65) else 0.5
        return abs(field_a - field_b) / polarity_match

    def polarity(self, token: Token) -> str:
        """Get polarity for token."""
        if token.basin < PRIME_131 // 2:
            return "positive"
        elif token.basin > PRIME_131 // 2:
            return "negative"
        return "neutral"

    def field_strength(self, token: Token) -> float:
        """Get field strength for token."""
        return self._field_strength(token)
