"""
CAN Bus decoder for Chapter 10 data types
Supports Controller Area Network Bus (0x78)
"""

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


class CANBusDecoder(DataTypeDecoder):
    """Decoder for CAN Bus type (0x78)"""
    
    def __init__(self):
        super().__init__()
        self.data_type_base = 0x78
        self.data_type_name = "CAN Bus"
        self.supported_formats = [0x78]
    
    def can_decode(self, data_type: int) -> bool:
        return data_type == 0x78
    
    def get_data_type_name(self, data_type: int) -> str:
        return "Controller Area Network Bus"
    
    def decode(self, payload: bytes, ch10_header: Dict[str, Any]) -> Optional[DecodedPayload]:
        """Decode CAN Bus payload"""
        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 CAN messages
        messages = []
        offset = data_start
        
        while offset + 16 <= len(payload):
            can_header = self._safe_unpack('<IIII', payload, offset)
            if not can_header:
                break
                
            can_timestamp, can_id_flags, data_length, reserved = can_header
            
            # Parse CAN ID and flags
            can_id = can_id_flags & 0x1FFFFFFF
            extended_id = bool(can_id_flags & 0x80000000)
            remote_frame = bool(can_id_flags & 0x40000000)
            error_frame = bool(can_id_flags & 0x20000000)
            
            message = {
                'timestamp': can_timestamp,
                'can_id': f'0x{can_id:x}',
                'extended_id': extended_id,
                'remote_frame': remote_frame,
                'error_frame': error_frame,
                'data_length': data_length
            }
            
            # Extract CAN data
            can_data_start = offset + 16
            if can_data_start + data_length <= len(payload):
                can_data = payload[can_data_start:can_data_start + data_length]
                message['data'] = can_data.hex()
                message['data_bytes'] = list(can_data)
            else:
                message['data_error'] = 'Data extends beyond payload'
            
            messages.append(message)
            offset = can_data_start + max(data_length, 8)  # CAN frames are padded to 8 bytes
            
            if len(messages) >= 100:  # Limit output size
                break
        
        decoded_data['can_messages'] = messages
        decoded_data['message_count'] = len(messages)
        
        # Statistics
        if messages:
            extended_count = sum(1 for msg in messages if msg['extended_id'])
            remote_count = sum(1 for msg in messages if msg['remote_frame'])
            error_count = sum(1 for msg in messages if msg['error_frame'])
            
            decoded_data['statistics'] = {
                'extended_frames': extended_count,
                'remote_frames': remote_count,
                'error_frames': error_count,
                'standard_frames': len(messages) - extended_count
            }
        
        return DecodedPayload(
            data_type=0x78,
            data_type_name="Controller Area Network Bus",
            format_version=0,
            decoded_data=decoded_data,
            raw_payload=payload,
            errors=errors,
            metadata={'decoder': 'CANBusDecoder'}
        )