#!/usr/bin/env python3
"""
Compact Buffer Widget - One Line Display
=========================================
Minimal, compact widget showing everything in ONE line.

Shows: [Capacity] [Progress Bar] [Overflow]

Manual update - call update_display() when you want.
"""

from PyQt6.QtWidgets import QWidget, QHBoxLayout, QLabel, QProgressBar
from PyQt6.QtCore import Qt
from .circular_buffer import (
    CircularBufferHandle,
    cb_capacity, cb_fill_bytes, cb_fill_pct, cb_overflows
)


def format_bytes(b: int) -> str:
    """
    Format byte count as human-readable string.

    Args:
        b: Byte count

    Returns:
        Formatted string (e.g., "120.5KB", "400.0MB", "1.2GB")
    """
    if b >= 1024**3:  # GB
        return f"{b / (1024**3):.1f}GB"
    elif b >= 1024**2:  # MB
        return f"{b / (1024**2):.1f}MB"
    elif b >= 1024:  # KB
        return f"{b / 1024:.1f}KB"
    else:
        return f"{b}B"


class CompactBufferWidget(QWidget):
    """
    Compact one-line buffer display.
    
    Layout: [Size Label] [===== Progress Bar =====] [Overflow]
    
    Usage:
        widget = CompactBufferWidget(buffer)
        
        # Update manually:
        widget.update_display()
    """
    
    def __init__(self, buffer: CircularBufferHandle, parent=None):
        super().__init__(parent)
        self.buffer = buffer
        
        # Horizontal layout (everything in ONE line)
        layout = QHBoxLayout()
        layout.setContentsMargins(2, 2, 2, 2)  # Tight margins
        layout.setSpacing(5)
        self.setLayout(layout)
        
        # Size label (left)
        self.lbl_size = QLabel()
        self.lbl_size.setMinimumWidth(80)
        layout.addWidget(self.lbl_size)
        
        # Progress bar (center - takes most space)
        self.progress = QProgressBar()
        self.progress.setRange(0, 100)
        self.progress.setTextVisible(True)
        self.progress.setFormat("%p%")
        self.progress.setMaximumHeight(20)  # Compact height
        layout.addWidget(self.progress, stretch=1)  # Stretch to fill
        
        # Overflow label (right)
        self.lbl_overflow = QLabel()
        self.lbl_overflow.setMinimumWidth(100)  # Wider for "Overflows: X"
        self.lbl_overflow.setAlignment(Qt.AlignmentFlag.AlignRight)
        layout.addWidget(self.lbl_overflow)
        
        self.update_display()
    
    def update_display(self):
        """Update display - call manually when needed."""
        cap = cb_capacity(self.buffer)
        fill = cb_fill_bytes(self.buffer)
        pct = cb_fill_pct(self.buffer)
        ovf = cb_overflows(self.buffer)

        # Update labels with human-readable format
        self.lbl_size.setText(f"{format_bytes(fill)}/{format_bytes(cap)}")
        self.progress.setValue(pct)
        
        # Overflow label - just show count (no color logic)
        self.lbl_overflow.setText(f"Overflows: {ovf}")
        if ovf > 0:
            self.lbl_overflow.setStyleSheet("color: red; font-weight: bold;")
        else:
            self.lbl_overflow.setStyleSheet("color: gray;")


# =============================================================================
# Version with callback support
# =============================================================================

class CompactBufferWidgetWithCallback(QWidget):
    """
    Compact widget WITH callback support.
    
    Callback is called whenever update_display() is called.
    Useful for logging, debugging, or triggering other actions.
    
    Usage:
        def my_callback(capacity, fill, percent, overflows):
            print(f"Buffer: {fill}/{capacity} ({percent}%)")
        
        widget = CompactBufferWidgetWithCallback(buffer, on_update=my_callback)
        widget.update_display()  # Callback is called!
    """
    
    def __init__(self, buffer: CircularBufferHandle, 
                 on_update=None, parent=None):
        """
        Args:
            buffer: CircularBufferHandle to monitor
            on_update: Callback function(capacity, fill, percent, overflows)
            parent: Parent widget
        """
        super().__init__(parent)
        self.buffer = buffer
        self.on_update_callback = on_update
        
        # Same layout as compact version
        layout = QHBoxLayout()
        layout.setContentsMargins(2, 2, 2, 2)
        layout.setSpacing(5)
        self.setLayout(layout)
        
        self.lbl_size = QLabel()
        self.lbl_size.setMinimumWidth(80)
        layout.addWidget(self.lbl_size)
        
        self.progress = QProgressBar()
        self.progress.setRange(0, 100)
        self.progress.setTextVisible(True)
        self.progress.setFormat("%p%")
        self.progress.setMaximumHeight(20)
        layout.addWidget(self.progress, stretch=1)
        
        self.lbl_overflow = QLabel()
        self.lbl_overflow.setMinimumWidth(100)  # Wider for "Overflows: X"
        self.lbl_overflow.setAlignment(Qt.AlignmentFlag.AlignRight)
        layout.addWidget(self.lbl_overflow)
        
        self.update_display()
    
    def update_display(self):
        """
        Update display and call callback if set.

        Callback signature:
            callback(capacity: int, fill: int, percent: int, overflows: int)
        """
        cap = cb_capacity(self.buffer)
        fill = cb_fill_bytes(self.buffer)
        pct = cb_fill_pct(self.buffer)
        ovf = cb_overflows(self.buffer)

        # Update UI with human-readable format
        self.lbl_size.setText(f"{format_bytes(fill)}/{format_bytes(cap)}")
        self.progress.setValue(pct)
        
        # Overflow label - just show count
        self.lbl_overflow.setText(f"Overflows: {ovf}")
        if ovf > 0:
            self.lbl_overflow.setStyleSheet("color: red; font-weight: bold;")
        else:
            self.lbl_overflow.setStyleSheet("color: gray;")
        
        # Call callback if set
        if self.on_update_callback:
            try:
                self.on_update_callback(cap, fill, pct, ovf)
            except Exception as e:
                print(f"Callback error: {e}")


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

def demo():
    """Demo showing both widgets."""
    import sys
    from PyQt6.QtWidgets import (
        QApplication, QMainWindow, QVBoxLayout, 
        QWidget, QPushButton, QLabel, QGroupBox
    )
    from circular_buffer import cb_init, cb_write
    
    class DemoWindow(QMainWindow):
        def __init__(self):
            super().__init__()
            self.setWindowTitle("Compact Buffer Widget Demo")
            
            central = QWidget()
            self.setCentralWidget(central)
            layout = QVBoxLayout()
            central.setLayout(layout)
            
            # Title
            title = QLabel("Compact One-Line Buffer Widgets")
            title.setStyleSheet("font-size: 14px; font-weight: bold;")
            layout.addWidget(title)
            
            # ====== Widget 1: Without callback ======
            group1 = QGroupBox("Widget 1: Basic (no callback)")
            group1_layout = QVBoxLayout()
            group1.setLayout(group1_layout)
            
            status1, self.buffer1 = cb_init(100)
            self.widget1 = CompactBufferWidget(self.buffer1)
            group1_layout.addWidget(self.widget1)
            
            layout.addWidget(group1)
            
            # ====== Widget 2: With callback ======
            group2 = QGroupBox("Widget 2: With Callback")
            group2_layout = QVBoxLayout()
            group2.setLayout(group2_layout)
            
            status2, self.buffer2 = cb_init(100)
            
            # Define callback
            def on_buffer_update(cap, fill, pct, ovf):
                print(f"Callback: {fill}/{cap}B ({pct}%) - Overflows: {ovf}")
            
            self.widget2 = CompactBufferWidgetWithCallback(
                self.buffer2, 
                on_update=on_buffer_update
            )
            group2_layout.addWidget(self.widget2)
            
            layout.addWidget(group2)
            
            # ====== Controls ======
            controls = QGroupBox("Controls")
            controls_layout = QVBoxLayout()
            controls.setLayout(controls_layout)
            
            btn_write_5 = QPushButton("Write 5 bytes to both")
            btn_write_5.clicked.connect(self.write_5)
            controls_layout.addWidget(btn_write_5)
            
            btn_write_50 = QPushButton("Write 50 bytes to both")
            btn_write_50.clicked.connect(self.write_50)
            controls_layout.addWidget(btn_write_50)
            
            btn_update = QPushButton("⟳ Update Displays")
            btn_update.setStyleSheet("background-color: #4CAF50; color: white;")
            btn_update.clicked.connect(self.update_all)
            controls_layout.addWidget(btn_update)
            
            layout.addWidget(controls)
            
            # Instructions
            instructions = QLabel(
                "\n💡 Instructions:\n"
                "1. Click 'Write X bytes' to add data\n"
                "2. Click 'Update Displays' to refresh\n"
                "3. Widget 2 prints callback info to console"
            )
            instructions.setStyleSheet("background-color: #f0f0f0; padding: 5px;")
            layout.addWidget(instructions)
            
            self.resize(500, 400)
        
        def write_5(self):
            cb_write(self.buffer1, b"HELLO")
            cb_write(self.buffer2, b"HELLO")
            print("Wrote 5 bytes - click Update to see")
        
        def write_50(self):
            cb_write(self.buffer1, b"X" * 50)
            cb_write(self.buffer2, b"X" * 50)
            print("Wrote 50 bytes - click Update to see")
        
        def update_all(self):
            print("\n--- Updating displays ---")
            self.widget1.update_display()
            self.widget2.update_display()  # This calls the callback!
    
    app = QApplication(sys.argv)
    window = DemoWindow()
    window.show()
    
    print("\n" + "="*60)
    print("COMPACT BUFFER WIDGET DEMO")
    print("="*60)
    print("Widget 1: Basic compact widget")
    print("Widget 2: Same but with callback function")
    print("\nClick buttons and watch:")
    print("  • Compact one-line display")
    print("  • Manual updates")
    print("  • Callback prints to console")
    print("="*60 + "\n")
    
    sys.exit(app.exec())


if __name__ == "__main__":
    demo()
