"""
IEEE 1394 Data decoders for Chapter 10 data types
Supports IEEE 1394 Formats 0-1 (0x58-0x59)
"""

import struct
from typing import Dict, Any, Optional
from .base import DataTypeDecoder, DecodedPayload


class IEEE1394Decoder(DataTypeDecoder):
    """Decoder for IEEE 1394 Data types (0x58-0x59)"""
    
    def __init__(self):
        super().__init__()
        self.data_type_base = 0x58
        self.data_type_name = "IEEE 1394 Data"
        self.supported_formats = [0x58, 0x59]
    
    def can_decode(self, data_type: int) -> bool:
        return data_type in [0x58, 0x59]
    
    def get_data_type_name(self, data_type: int) -> str:
        format_names = {
            0x58: "IEEE 1394 Transaction",
            0x59: "IEEE 1394 Physical Layer"
        }
        return format_names.get(data_type, f"IEEE 1394 Format {data_type & 0x0F}")
    
    def decode(self, payload: bytes, ch10_header: Dict[str, Any]) -> Optional[DecodedPayload]:
        """Decode IEEE 1394 payload"""
        data_type = ch10_header.get('data_type', 0)
        
        if not self.can_decode(data_type):
            return None
        
        if data_type == 0x58:
            return self._decode_transaction(payload, ch10_header)
        elif data_type == 0x59:
            return self._decode_physical_layer(payload, ch10_header)
        
        return None
    
    def _decode_transaction(self, payload: bytes, ch10_header: Dict[str, Any]) -> DecodedPayload:
        """Decode IEEE 1394 Transaction data"""
        decoded_data = {}
        errors = []
        
        # Parse IPH
        iph = self._parse_intra_packet_header(payload)
        if iph:
            decoded_data.update(iph)
            data_start = iph['data_start']
        else:
            data_start = 0
            errors.append("Failed to parse intra-packet header")
        
        # Parse 1394 transaction header
        if data_start + 16 <= len(payload):
            tx_header = self._safe_unpack('<IIII', payload, data_start)
            if tx_header:
                decoded_data.update({
                    'transaction_timestamp': tx_header[0],
                    'transaction_code': tx_header[1] & 0x0F,
                    'source_id': (tx_header[1] >> 16) & 0xFFFF,
                    'destination_offset': tx_header[2],
                    'data_length': tx_header[3]
                })
                
                # Decode transaction code
                tx_codes = {
                    0: "Write Request",
                    1: "Write Response", 
                    4: "Read Request",
                    5: "Read Response",
                    6: "Lock Request",
                    7: "Lock Response"
                }
                decoded_data['transaction_type'] = tx_codes.get(
                    decoded_data['transaction_code'], 
                    f"Unknown ({decoded_data['transaction_code']})"
                )
                
                # Extract transaction data
                tx_data_start = data_start + 16
                tx_data_length = decoded_data['data_length']
                if tx_data_start + tx_data_length <= len(payload):
                    tx_data = payload[tx_data_start:tx_data_start + tx_data_length]
                    decoded_data['transaction_data'] = tx_data[:64].hex()
            else:
                errors.append("Failed to parse 1394 transaction header")
        
        return DecodedPayload(
            data_type=0x58,
            data_type_name="IEEE 1394 Transaction",
            format_version=0,
            decoded_data=decoded_data,
            raw_payload=payload,
            errors=errors,
            metadata={'decoder': 'IEEE1394Decoder'}
        )
    
    def _decode_physical_layer(self, payload: bytes, ch10_header: Dict[str, Any]) -> DecodedPayload:
        """Decode IEEE 1394 Physical Layer data"""
        decoded_data = {}
        errors = []
        
        # Parse IPH
        iph = self._parse_intra_packet_header(payload)
        if iph:
            decoded_data.update(iph)
            data_start = iph['data_start']
        else:
            data_start = 0
            errors.append("Failed to parse intra-packet header")
        
        # Parse physical layer data
        if data_start < len(payload):
            phy_data = payload[data_start:]
            decoded_data['phy_data_length'] = len(phy_data)
            decoded_data['phy_data_hex'] = phy_data[:64].hex()
            
            # Basic PHY packet analysis
            if len(phy_data) >= 4:
                phy_header = struct.unpack('<I', phy_data[:4])[0]
                decoded_data['phy_packet_type'] = (phy_header >> 28) & 0x0F
                decoded_data['phy_speed'] = (phy_header >> 26) & 0x03
                
                speed_names = {0: "100 Mbps", 1: "200 Mbps", 2: "400 Mbps", 3: "Reserved"}
                decoded_data['phy_speed_description'] = speed_names.get(
                    decoded_data['phy_speed'], "Unknown"
                )
        
        return DecodedPayload(
            data_type=0x59,
            data_type_name="IEEE 1394 Physical Layer",
            format_version=1,
            decoded_data=decoded_data,
            raw_payload=payload,
            errors=errors,
            metadata={'decoder': 'IEEE1394Decoder'}
        )