# core/payload_router.py
"""
Defines the PayloadRouter class, responsible for directing incoming,
reassembled SFP payloads to the correct application-level handler.
"""

import logging
import json
from typing import Dict, Callable

# Definisci il tipo per un handler, se vuoi essere più esplicito
PayloadHandler = Callable[[bytearray], None]


class PayloadRouter:
    """
    Inspects SFP flow IDs and routes payloads to registered handlers.
    Also contains the implementations for each specific payload handler.
    """

    def __init__(self):
        self._log_prefix = "[PayloadRouter]"
        logging.info(f"{self._log_prefix} Initializing...")

    def get_handlers(self) -> Dict[int, PayloadHandler]:
        """
        Returns a dictionary mapping SFP_FLOW IDs to their handler methods.
        This is the primary method used to connect this router to the transport layer.

        Returns:
            Dict[int, PayloadHandler]: The dictionary of flow IDs and handlers.
        """
        handlers = {
            ord("M"): self.handle_mfd_image_payload,
            ord("S"): self.handle_sar_image_payload,
            ord("B"): self.handle_binary_data_payload,
            ord("J"): self.handle_json_payload,
            # Aggiungi qui nuovi flussi e handler
        }
        logging.debug(
            f"{self._log_prefix} Providing handlers for flows: {[chr(k) if 32<=k<=126 else k for k in handlers.keys()]}"
        )
        return handlers

    # --- Handler Implementations ---

    def handle_mfd_image_payload(self, payload: bytearray):
        """Handler for MFD image payloads."""
        log_prefix = f"{self._log_prefix} MFD"
        logging.info(
            f"{log_prefix} Received payload. Size: {len(payload)} bytes. Processing..."
        )
        # Qui la logica per interpretare il payload dell'immagine MFD
        # Ad esempio, potresti usare ctypes per mappare una struttura dati:
        # from .sfp_structures import ImageLeaderData
        # image_leader = ImageLeaderData.from_buffer(payload)
        # logging.debug(f"{log_prefix} Frame counter: {image_leader.HEADER_DATA.FCOUNTER}")
        pass

    def handle_sar_image_payload(self, payload: bytearray):
        """Handler for SAR image payloads."""
        log_prefix = f"{self._log_prefix} SAR"
        logging.info(
            f"{log_prefix} Received payload. Size: {len(payload)} bytes. Processing..."
        )
        # Qui la logica per interpretare il payload dell'immagine SAR
        pass

    def handle_binary_data_payload(self, payload: bytearray):
        """Handler for generic binary data payloads."""
        log_prefix = f"{self._log_prefix} BIN"
        logging.info(f"{log_prefix} Received payload. Size: {len(payload)} bytes.")
        try:
            # Esempio: leggi un ID (2 byte), una lunghezza (4 byte) e dei dati
            if len(payload) >= 6:
                message_id = int.from_bytes(payload[0:2], "little")
                data_length = int.from_bytes(payload[2:6], "little")
                actual_data = payload[6 : 6 + data_length]
                logging.info(
                    f"{log_prefix} Parsed binary message: ID={message_id}, Length={data_length}, Data size={len(actual_data)}"
                )
            else:
                logging.warning(
                    f"{log_prefix} Payload too small for expected binary format."
                )
        except Exception as e:
            logging.error(f"{log_prefix} Error parsing binary payload: {e}")

    def handle_json_payload(self, payload: bytearray):
        """Handler for JSON payloads."""
        log_prefix = f"{self._log_prefix} JSON"
        logging.info(f"{log_prefix} Received payload. Size: {len(payload)} bytes.")
        try:
            json_string = payload.decode("utf-8")
            data = json.loads(json_string)
            message_type = data.get("type", "Unknown")
            logging.info(f"{log_prefix} Decoded JSON message of type '{message_type}'.")
            # Qui la logica per processare l'oggetto JSON
            # if message_type == 'status_update':
            #     handle_status_update(data)
        except (UnicodeDecodeError, json.JSONDecodeError) as e:
            logging.error(f"{log_prefix} Error decoding JSON payload: {e}")
