"""
CPU Grid System Application

This application manages a 2000 CPU grid system with:
- 500 UI/Display CPUs
- 500 Computation CPUs
- 500 I/O & Storage CPUs
- 500 System Tasks CPUs

Each CPU has:
- 50 physical cores
- 100 threads per core
"""

from enhanced_cpu import CPUGrid, CPUGroupType, CPUInstruction, InstructionType
import threading
import queue
import time

class CPUGridManager:
    def __init__(self):
        self.grid = CPUGrid()
        self.task_queues = {
            CPUGroupType.UI_DISPLAY: queue.Queue(),
            CPUGroupType.COMPUTATION: queue.Queue(),
            CPUGroupType.IO_STORAGE: queue.Queue(),
            CPUGroupType.SYSTEM_TASKS: queue.Queue()
        }
        self.running = True
        self._start_task_dispatchers()
        
    def _start_task_dispatchers(self):
        """Start dispatcher threads for each CPU group"""
        for group_type in CPUGroupType:
            thread = threading.Thread(
                target=self._dispatch_tasks,
                args=(group_type,),
                daemon=True
            )
            thread.start()
            
    def _dispatch_tasks(self, group_type: CPUGroupType):
        """Dispatch tasks to available CPUs in the group"""
        while self.running:
            try:
                task = self.task_queues[group_type].get(timeout=0.1)
                if task:
                    # Find an available CPU in the group
                    cpu = self.grid.get_available_cpu(group_type)
                    if cpu:
                        # Create instruction from task
                        instruction = CPUInstruction(
                            type=task['type'],
                            opcode=task['opcode'],
                            operands=task['operands'],
                            data=task.get('data')
                        )
                        # Schedule instruction on CPU
                        cpu.schedule_instruction(instruction)
                    else:
                        # Re-queue task if no CPU available
                        self.task_queues[group_type].put(task)
                        time.sleep(0.1)
            except queue.Empty:
                continue
                
    def submit_task(self, group_type: CPUGroupType, task: dict):
        """Submit a task to be processed by a CPU in the specified group"""
        self.task_queues[group_type].put(task)
        
    def shutdown(self):
        """Gracefully shutdown the CPU grid"""
        self.running = False
        self.grid.shutdown()
        
if __name__ == "__main__":
    manager = CPUGridManager()
    try:
        # Example tasks
        ui_task = {
            'type': InstructionType.ARITHMETIC,
            'opcode': 0x01,  # ADD
            'operands': [5, 3]
        }
        
        compute_task = {
            'type': InstructionType.MEMORY,
            'opcode': 0x02,  # WRITE
            'operands': [0x1000],  # Memory address
            'data': b'Hello, World!'
        }
        
        io_task = {
            'type': InstructionType.IO,
            'opcode': 0x01,  # READ
            'operands': [1500]  # CPU ID to read state from
        }
        
        # Submit tasks
        manager.submit_task(CPUGroupType.UI_DISPLAY, ui_task)
        manager.submit_task(CPUGroupType.COMPUTATION, compute_task)
        manager.submit_task(CPUGroupType.IO_STORAGE, io_task)
        
        # Keep running for demo
        time.sleep(10)
        
    finally:
        manager.shutdown()
