#!/usr/bin/env python3
"""
Módulo de Monitoramento VSWR do FastChecker II

Responsável por:
- Monitoramento constante de VSWR
- Status OK/NOK
- Parada automática se VSWR > 10
- Integração com comandos do antenna check
"""

import time
import threading
from typing import Optional, Callable
from enum import Enum
import logging

# Configurar logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


class VSWRStatus(Enum):
    """Status do monitoramento VSWR"""
    OK = "OK"
    NOK = "NOK"
    ERROR = "Erro"


class VSWRMonitor:
    """
    Monitor de VSWR do reader RFID
    
    Funcionalidades:
    - Monitoramento constante de VSWR
    - Status OK/NOK
    - Parada automática se VSWR > 10
    - Callbacks para atualização de interface
    """
    
    def __init__(self, reader_interface=None):
        """
        Inicializa o monitor de VSWR
        
        Args:
            reader_interface: Interface para comunicação com o reader
        """
        self.reader_interface = reader_interface
        self.status = VSWRStatus.ERROR
        self.current_vswr = 0.0
        self.critical_vswr = 10.0  # VSWR crítico para parada
        self.monitoring = False
        self.monitor_thread = None
        self.status_callback: Optional[Callable] = None
        self.vswr_callback: Optional[Callable] = None
        self.critical_callback: Optional[Callable] = None
        
        logger.info("Monitor de VSWR inicializado")
    
    def set_callbacks(self, status_callback=None, vswr_callback=None, critical_callback=None):
        """
        Define callbacks para atualização da interface
        
        Args:
            status_callback: Callback para atualizar status (OK/NOK)
            vswr_callback: Callback para atualizar valor VSWR
            critical_callback: Callback para parada por VSWR crítico
        """
        self.status_callback = status_callback
        self.vswr_callback = vswr_callback
        self.critical_callback = critical_callback
    
    def read_vswr(self) -> float:
        """
        Lê o VSWR atual do reader
        
        Returns:
            float: Valor de VSWR
        """
        try:
            if self.reader_interface:
                # Usar método get_vswr do FastSurance se disponível
                if hasattr(self.reader_interface, 'get_vswr'):
                    # Usar potência padrão para medição de VSWR
                    vswr = self.reader_interface.get_vswr(tx_power_dbm=25.0)
                    if vswr is not None:
                        self.current_vswr = vswr
                        return self.current_vswr
                    else:
                        logger.error("Falha ao ler VSWR do hardware")
                        return self.current_vswr
                else:
                    # Fallback para acesso direto ao hardware
                    if hasattr(self.reader_interface, 'hardware_controller'):
                        import ctypes, struct
                        # Tentar abrir a porta se necessário
                        if self.reader_interface.hardware_controller.find_and_open_port():
                            output_buffer = ctypes.create_string_buffer(64)
                            output_len = ctypes.c_uint(0)
                            dll = self.reader_interface.hardware_controller.dll
                            
                            # Configurar potência para medição
                            power_data = bytes([0,0]) + int(25.0 * 100).to_bytes(2, 'big')*2
                            dll.UHF_RFID_Set(0x31, ctypes.c_char_p(power_data), 6, output_buffer, ctypes.byref(output_len))
                            
                            # Ler perda de retorno
                            status = dll.UHF_RFID_Set(0x35, b'', 0, output_buffer, ctypes.byref(output_len))
                            if status == 0 and output_len.value >= 3:
                                adc_value = struct.unpack('>H', output_buffer.raw[1:3])[0]
                                
                                # Tabela de conversão de RX_ADC para Potência Refletida
                                RxAdcTable = [
                                    0x0000, 0x0000, 0x0000, 0x0001, 0x0002, 0x0005, 0x0007, 0x000B, 0x0010, 0x0116, 0x011D, 0x0126,
                                    0x0131, 0x013E, 0x024C, 0x0260, 0x0374, 0x048B, 0x05A5, 0x06C3, 0x08E6, 0x09FF, 0x0BFF, 0x0EFF,
                                    0x10FF, 0x14FF, 0x17FF, 0x1CFF, 0x21FF, 0x26FF, 0x2DFF, 0x34FF, 0x3CFF, 0x46FF, 0x50FF, 0x5DFF,
                                    0x6AFF, 0x7AFF, 0x8BFF, 0x9EFF, 0xB4FF, 0xCCFF, 0xE7FF, 0xFFFF
                                ]
                                
                                reflected_power_dbm = -25 + next((i for i, val in enumerate(RxAdcTable) if adc_value <= val), len(RxAdcTable) - 1)
                                tx_power_dbm = 25.0
                                
                                if reflected_power_dbm >= tx_power_dbm: 
                                    self.current_vswr = 99.0
                                    return self.current_vswr
                                
                                perda_retorno_db = float(tx_power_dbm) - float(reflected_power_dbm)
                                if perda_retorno_db < 0: 
                                    self.current_vswr = 99.0
                                    return self.current_vswr
                                
                                gamma = 10**(-perda_retorno_db / 20)
                                vswr = (1 + gamma) / (1 - gamma)
                                self.current_vswr = vswr
                                return self.current_vswr
                            else:
                                logger.error("Falha ao ler VSWR do hardware")
                                return self.current_vswr
                        else:
                            logger.error("Falha ao abrir porta para leitura de VSWR")
                            return self.current_vswr
                    else:
                        logger.error("Interface não tem hardware_controller")
                        return self.current_vswr
            else:
                logger.error("Interface do reader não disponível")
                return self.current_vswr
        except Exception as e:
            logger.error(f"Erro ao ler VSWR: {e}")
            return self.current_vswr
    
    def update_status(self, new_status: VSWRStatus):
        """
        Atualiza o status e notifica interface
        
        Args:
            new_status: Novo status de VSWR
        """
        if self.status != new_status:
            self.status = new_status
            logger.info(f"Status de VSWR: {new_status.value}")
            
            if self.status_callback:
                self.status_callback(new_status.value)
    
    def update_vswr_display(self, vswr: float):
        """
        Atualiza display de VSWR
        
        Args:
            vswr: Valor de VSWR atual
        """
        if self.vswr_callback:
            self.vswr_callback(vswr)
    
    def is_critical(self) -> bool:
        """
        Verifica se VSWR está crítico
        
        Returns:
            bool: True se VSWR > 10
        """
        return self.current_vswr > self.critical_vswr
    
    def is_ok(self) -> bool:
        """
        Verifica se VSWR está adequado
        
        Returns:
            bool: True se VSWR ≤ 10
        """
        return self.current_vswr <= self.critical_vswr
    
    def monitor_vswr(self):
        """
        Loop principal de monitoramento de VSWR
        """
        while self.monitoring:
            try:
                # Lê VSWR atual
                vswr = self.read_vswr()
                self.current_vswr = vswr
                
                # Atualiza display
                self.update_vswr_display(vswr)
                
                # Verifica VSWR crítico
                if self.is_critical():
                    logger.warning(f"VSWR crítico: {vswr:.2f}")
                    self.update_status(VSWRStatus.NOK)
                    
                    if self.critical_callback:
                        self.critical_callback(vswr)
                else:
                    if self.status != VSWRStatus.OK:
                        self.update_status(VSWRStatus.OK)
                
                # Aguarda antes da próxima leitura
                time.sleep(0.5)
                
            except Exception as e:
                logger.error(f"Erro no monitoramento de VSWR: {e}")
                self.update_status(VSWRStatus.ERROR)
                time.sleep(1)
    
    def start_monitoring(self):
        """Inicia o monitoramento de VSWR em thread separada"""
        if not self.monitoring:
            self.monitoring = True
            self.monitor_thread = threading.Thread(
                target=self.monitor_vswr,
                daemon=True
            )
            self.monitor_thread.start()
            logger.info("Monitoramento de VSWR iniciado")
    
    def stop_monitoring(self):
        """Para o monitoramento de VSWR"""
        self.monitoring = False
        if self.monitor_thread:
            self.monitor_thread.join(timeout=1)
        logger.info("Monitoramento de VSWR parado")
    
    def get_status(self) -> str:
        """
        Retorna o status atual como string
        
        Returns:
            str: Status atual (OK/NOK/Erro)
        """
        return self.status.value
    
    def get_vswr(self) -> float:
        """
        Retorna o VSWR atual
        
        Returns:
            float: Valor de VSWR
        """
        return self.current_vswr
    
    def is_ready(self) -> bool:
        """
        Verifica se VSWR está pronto para operação
        
        Returns:
            bool: True se VSWR está adequado
        """
        return self.status == VSWRStatus.OK
    
    def cleanup(self):
        """Limpa recursos do monitor"""
        self.stop_monitoring()
        logger.info("Monitor de VSWR finalizado")


# Função de conveniência para criar monitor
def create_vswr_monitor(reader_interface=None) -> VSWRMonitor:
    """
    Cria uma instância do monitor de VSWR
    
    Args:
        reader_interface: Interface do reader
        
    Returns:
        VSWRMonitor: Instância do monitor
    """
    return VSWRMonitor(reader_interface)


if __name__ == "__main__":
    # Teste do monitor
    monitor = create_vswr_monitor()
    
    def status_callback(status):
        print(f"Status VSWR: {status}")
    
    def vswr_callback(vswr):
        print(f"VSWR: {vswr:.2f}")
    
    def critical_callback(vswr):
        print(f"ALERTA: VSWR crítico {vswr:.2f}!")
    
    monitor.set_callbacks(status_callback, vswr_callback, critical_callback)
    monitor.start_monitoring()
    
    try:
        time.sleep(10)  # Teste por 10 segundos
    except KeyboardInterrupt:
        pass
    finally:
        monitor.cleanup() 