"""
Live network capture utilities
"""

import sys
import threading
import time
from typing import Callable, Optional, List

try:
    from scapy.all import sniff, Packet, get_if_list
except ImportError:
    print("Error: scapy library required. Install with: pip install scapy")
    sys.exit(1)


class LiveCapture:
    """Utility class for live network capture"""
    
    def __init__(self, interface: Optional[str] = None, filter_str: Optional[str] = None):
        self.interface = interface
        self.filter_str = filter_str
        self.is_capturing = False
        self.stop_requested = False
        self.packet_count = 0
        self.capture_thread: Optional[threading.Thread] = None
        self.packet_handlers: List[Callable[[Packet, int], None]] = []
        
    def add_packet_handler(self, handler: Callable[[Packet, int], None]) -> None:
        """Add a packet handler function"""
        self.packet_handlers.append(handler)
    
    def remove_packet_handler(self, handler: Callable[[Packet, int], None]) -> None:
        """Remove a packet handler function"""
        if handler in self.packet_handlers:
            self.packet_handlers.remove(handler)
    
    def start_capture(self, threaded: bool = True) -> None:
        """Start packet capture"""
        if self.is_capturing:
            raise RuntimeError("Capture is already running")
        
        self.stop_requested = False
        self.packet_count = 0
        
        if threaded:
            self.capture_thread = threading.Thread(target=self._capture_loop, daemon=True)
            self.capture_thread.start()
        else:
            self._capture_loop()
    
    def stop_capture(self) -> None:
        """Stop packet capture"""
        self.stop_requested = True
        
        if self.capture_thread and self.capture_thread.is_alive():
            self.capture_thread.join(timeout=5.0)
            if self.capture_thread.is_alive():
                print("Warning: Capture thread did not stop gracefully")
    
    def _capture_loop(self) -> None:
        """Main capture loop"""
        self.is_capturing = True
        
        try:
            def packet_handler(packet: Packet) -> None:
                if self.stop_requested:
                    return
                
                self.packet_count += 1
                
                # Call all registered handlers
                for handler in self.packet_handlers:
                    try:
                        handler(packet, self.packet_count)
                    except Exception as e:
                        print(f"Error in packet handler: {e}")
            
            sniff(
                iface=self.interface,
                filter=self.filter_str,
                prn=packet_handler,
                stop_filter=lambda x: self.stop_requested
            )
            
        except Exception as e:
            print(f"Error during live capture: {e}")
        finally:
            self.is_capturing = False
    
    def get_capture_stats(self) -> dict:
        """Get capture statistics"""
        return {
            'is_capturing': self.is_capturing,
            'packet_count': self.packet_count,
            'interface': self.interface,
            'filter': self.filter_str
        }
    
    @staticmethod
    def list_interfaces() -> List[str]:
        """List available network interfaces"""
        try:
            return get_if_list()
        except Exception as e:
            print(f"Error listing interfaces: {e}")
            return []
    
    @staticmethod
    def validate_interface(interface: str) -> bool:
        """Validate that an interface exists"""
        try:
            available_interfaces = LiveCapture.list_interfaces()
            return interface in available_interfaces
        except Exception:
            return False
    
    @staticmethod
    def test_capture_permissions() -> bool:
        """Test if we have permissions for packet capture"""
        try:
            # Try a very short capture to test permissions
            def dummy_handler(packet):
                pass
            
            sniff(count=1, timeout=1, prn=dummy_handler)
            return True
        except Exception:
            return False