"""
WatchDog Manager - Hardware WatchDog Timer Interface
"""

import os
import sys
import time
import logging
from typing import Optional, Dict, Any

logger = logging.getLogger(__name__)

# Add lib path
script_dir = os.path.dirname(os.path.abspath(__file__))
parent_dir = os.path.dirname(script_dir)

class WatchDogManager:
    """Manager for hardware WatchDog operations"""
    
    def __init__(self, 
                 i2c_address: int = 0x67, 
                 i2c_bus: int = 1, 
                 gpio_pin: int = 4,
                 timeout: int = 60,
                 mock: bool = False):
        self.i2c_address = i2c_address
        self.i2c_bus = i2c_bus
        self.gpio_pin = gpio_pin
        self.timeout = timeout
        self.mock = mock
        self.bus = None
        self._available = False
        
        if not mock:
            self._init_watchdog()
    
    def _init_watchdog(self):
        """Initialize WatchDog connection"""
        try:
            import smbus
            import RPi.GPIO as GPIO
            
            self.bus = smbus.SMBus(self.i2c_bus)
            GPIO.setmode(GPIO.BCM)
            GPIO.setwarnings(False)
            GPIO.setup(self.gpio_pin, GPIO.OUT)
            
            self._available = True
            logger.info(f"WatchDog initialized at address 0x{self.i2c_address:02X}")
        except Exception as e:
            logger.error(f"Failed to initialize WatchDog: {e}")
            self._available = False
    
    @property
    def available(self) -> bool:
        """Check if WatchDog is available"""
        return self._available or self.mock
    
    def feed(self) -> bool:
        """Feed the watchdog to prevent timeout"""
        if self.mock:
            logger.debug("Mock: WatchDog fed")
            return True
        
        if not self.bus:
            logger.warning("WatchDog not available")
            return False
        
        try:
            import RPi.GPIO as GPIO
            # Toggle GPIO pin to feed watchdog
            GPIO.output(self.gpio_pin, GPIO.HIGH)
            time.sleep(0.1)
            GPIO.output(self.gpio_pin, GPIO.LOW)
            logger.debug("WatchDog fed")
            return True
        except Exception as e:
            logger.error(f"Failed to feed WatchDog: {e}")
            return False
    
    def get_version(self) -> Optional[Dict[str, Any]]:
        """Get WatchDog firmware version"""
        if self.mock:
            return {"version": 1, "mock": True}
        
        if not self.bus:
            return None
        
        try:
            version = self.bus.read_byte_data(self.i2c_address, 0x05)
            return {
                "version": version,
                "mock": False
            }
        except Exception as e:
            logger.error(f"Failed to get WatchDog version: {e}")
            return None
    
    def get_status(self) -> Dict[str, Any]:
        """Get complete WatchDog status"""
        status = {
            "available": self.available,
            "mock": self.mock,
            "i2c_address": f"0x{self.i2c_address:02X}",
            "i2c_bus": self.i2c_bus,
            "gpio_pin": self.gpio_pin,
            "timeout": self.timeout
        }
        
        version = self.get_version()
        if version:
            status["version"] = version["version"]
        
        return status
    
    def test_feed_loop(self, count: int = 10, interval: float = 5.0):
        """Test watchdog feeding loop"""
        logger.info(f"Starting WatchDog test loop ({count} iterations)")
        
        for i in range(count):
            if self.feed():
                logger.info(f"[{i+1}/{count}] WatchDog fed successfully")
            else:
                logger.error(f"[{i+1}/{count}] Failed to feed WatchDog")
            
            if i < count - 1:
                time.sleep(interval)
        
        logger.info("WatchDog test loop completed")
    
    def __del__(self):
        """Cleanup GPIO on destruction"""
        try:
            import RPi.GPIO as GPIO
            GPIO.cleanup(self.gpio_pin)
        except:
            pass
