#!/usr/bin/env python3
"""
Global Clock - Timestamp Synchronization
=========================================
Singleton clock for synchronizing timestamps across UART, I2C, and other modules.

All timestamps use the same time reference (app start), enabling:
- Aligned plotting of UART and I2C data
- Consistent timeline across all modules
- Database storage with unified timestamp column

Usage:
    from global_clock import GlobalClock
    
    clock = GlobalClock.instance()
    timestamp = clock.now()  # Seconds since app start

Author: Kynsight
Version: 1.0.0
"""

import time
from typing import Optional


class GlobalClock:
    """
    Singleton clock for application-wide timestamp synchronization.
    
    Uses monotonic time (time.perf_counter) for stability.
    All timestamps are relative to application start time.
    """
    
    _instance: Optional['GlobalClock'] = None
    
    def __init__(self):
        """Initialize clock at application start."""
        self._start_time = time.perf_counter()
    
    @classmethod
    def instance(cls) -> 'GlobalClock':
        """Get singleton instance (creates if needed)."""
        if cls._instance is None:
            cls._instance = GlobalClock()
        return cls._instance
    
    def now(self) -> float:
        """
        Get current timestamp in seconds since app start.
        
        Returns:
            float: Time in seconds (e.g., 123.456789)
        """
        return time.perf_counter() - self._start_time
    
    def now_ns(self) -> int:
        """
        Get current timestamp in nanoseconds since app start.
        
        Returns:
            int: Time in nanoseconds
        """
        return int((time.perf_counter() - self._start_time) * 1_000_000_000)
    
    def reset(self):
        """Reset clock to zero (useful for testing or new sessions)."""
        self._start_time = time.perf_counter()


# =============================================================================
# Module-level convenience functions
# =============================================================================

def now() -> float:
    """
    Get current timestamp (seconds since app start).
    
    Convenience function for GlobalClock.instance().now()
    """
    return GlobalClock.instance().now()


def now_ns() -> int:
    """
    Get current timestamp (nanoseconds since app start).
    
    Convenience function for GlobalClock.instance().now_ns()
    """
    return GlobalClock.instance().now_ns()


# =============================================================================
# Demo
# =============================================================================

if __name__ == "__main__":
    import time as time_module
    
    print("Global Clock Demo")
    print("=" * 50)
    
    # Get clock instance
    clock = GlobalClock.instance()
    
    print(f"App start time: {clock.now():.6f}s")
    
    # Simulate some operations
    time_module.sleep(0.1)
    print(f"After 100ms: {clock.now():.6f}s")
    
    time_module.sleep(0.2)
    print(f"After 300ms total: {clock.now():.6f}s")
    
    # Nanosecond precision
    print(f"\nNanoseconds: {clock.now_ns()} ns")
    
    # Demonstrate synchronization
    print("\n" + "=" * 50)
    print("Synchronization Demo:")
    print("=" * 50)
    
    uart_timestamp = clock.now()
    print(f"UART packet at: {uart_timestamp:.6f}s")
    
    time_module.sleep(0.05)
    
    i2c_timestamp = clock.now()
    print(f"I2C reading at: {i2c_timestamp:.6f}s")
    
    print(f"\nTime difference: {(i2c_timestamp - uart_timestamp)*1000:.2f}ms")
    print("✓ Both timestamps use same reference!")
