#!/usr/bin/env python3
"""
Traffic Light Simulator (No Hardware Required)
==============================================
Simulates two-way traffic light operation using text output.
Perfect for testing logic without a Raspberry Pi or breadboard.

This demonstrates the exact same logic as the hardware versions,
but prints the state instead of controlling actual LEDs.

Usage:
------
python3 traffic_simulator.py

Author: Educational demonstration
"""

from time import sleep
import sys

class SimulatedTrafficLights:
    """
    Simulates a set of traffic lights with text output.
    """
    def __init__(self, name):
        self.name = name
        self.red = False
        self.amber = False
        self.green = False
    
    def set_state(self, red=False, amber=False, green=False):
        """Set the light state and display it."""
        self.red = red
        self.amber = amber
        self.green = green
    
    def display(self):
        """Return a visual representation of the light state."""
        lights = []
        lights.append('🔴' if self.red else '⚫')
        lights.append('🟡' if self.amber else '⚫')
        lights.append('🟢' if self.green else '⚫')
        return ' '.join(lights)
    
    def off(self):
        """Turn all lights off."""
        self.set_state(False, False, False)

def clear_screen():
    """Clear the terminal screen."""
    print("\033[2J\033[H", end='')

def display_intersection(lights_a, lights_b, phase_description):
    """
    Display the current state of the intersection.
    
    Args:
        lights_a: SimulatedTrafficLights object
        lights_b: SimulatedTrafficLights object
        phase_description: String describing current phase
    """
    clear_screen()
    
    print("=" * 60)
    print("TWO-WAY TRAFFIC LIGHT SIMULATION")
    print("=" * 60)
    print()
    print(f"Current Phase: {phase_description}")
    print()
    print(f"Direction A (North-South): {lights_a.display()}")
    print(f"Direction B (East-West):   {lights_b.display()}")
    print()
    print("Legend: 🔴 Red  🟡 Amber  🟢 Green  ⚫ Off")
    print()
    print("Press Ctrl+C to stop")
    print("=" * 60)

def two_way_simulation():
    """
    Run a two-way traffic light simulation.
    """
    # Create simulated traffic lights
    lights_a = SimulatedTrafficLights("Direction A")
    lights_b = SimulatedTrafficLights("Direction B")
    
    # Timing constants (in seconds)
    GREEN_TIME = 10
    AMBER_TIME = 3
    ALL_RED_TIME = 2
    RED_AMBER_TIME = 2
    
    # Initialize: Both red
    lights_a.set_state(red=True)
    lights_b.set_state(red=True)
    display_intersection(lights_a, lights_b, "Initialization - Both Red")
    sleep(2)
    
    try:
        cycle = 0
        while True:
            cycle += 1
            
            # Phase 1: A gets red+amber
            lights_a.set_state(red=True, amber=True)
            lights_b.set_state(red=True)
            display_intersection(lights_a, lights_b, 
                               f"Cycle {cycle}: A preparing to go")
            sleep(RED_AMBER_TIME)
            
            # Phase 2: A gets green
            lights_a.set_state(green=True)
            lights_b.set_state(red=True)
            display_intersection(lights_a, lights_b, 
                               f"Cycle {cycle}: A has priority (GO)")
            sleep(GREEN_TIME)
            
            # Phase 3: A gets amber
            lights_a.set_state(amber=True)
            lights_b.set_state(red=True)
            display_intersection(lights_a, lights_b, 
                               f"Cycle {cycle}: A prepare to stop")
            sleep(AMBER_TIME)
            
            # Phase 4: Both red (safety)
            lights_a.set_state(red=True)
            lights_b.set_state(red=True)
            display_intersection(lights_a, lights_b, 
                               f"Cycle {cycle}: Safety buffer - Both Red")
            sleep(ALL_RED_TIME)
            
            # Phase 5: B gets red+amber
            lights_a.set_state(red=True)
            lights_b.set_state(red=True, amber=True)
            display_intersection(lights_a, lights_b, 
                               f"Cycle {cycle}: B preparing to go")
            sleep(RED_AMBER_TIME)
            
            # Phase 6: B gets green
            lights_a.set_state(red=True)
            lights_b.set_state(green=True)
            display_intersection(lights_a, lights_b, 
                               f"Cycle {cycle}: B has priority (GO)")
            sleep(GREEN_TIME)
            
            # Phase 7: B gets amber
            lights_a.set_state(red=True)
            lights_b.set_state(amber=True)
            display_intersection(lights_a, lights_b, 
                               f"Cycle {cycle}: B prepare to stop")
            sleep(AMBER_TIME)
            
            # Phase 8: Both red (safety)
            lights_a.set_state(red=True)
            lights_b.set_state(red=True)
            display_intersection(lights_a, lights_b, 
                               f"Cycle {cycle}: Safety buffer - Both Red")
            sleep(ALL_RED_TIME)
    
    except KeyboardInterrupt:
        print("\n\nShutting down simulation...")
        lights_a.off()
        lights_b.off()
        print("Simulation ended. Goodbye!")

def three_way_simulation():
    """
    Run a three-way traffic light simulation (paired operation).
    """
    # Create simulated traffic lights
    lights_a = SimulatedTrafficLights("Direction A")
    lights_b = SimulatedTrafficLights("Direction B")
    lights_c = SimulatedTrafficLights("Direction C")
    
    # Timing constants
    MAIN_ROAD_GREEN = 12
    SIDE_ROAD_GREEN = 8
    AMBER_TIME = 3
    ALL_RED_TIME = 2
    RED_AMBER_TIME = 2
    
    # Initialize: All red
    lights_a.set_state(red=True)
    lights_b.set_state(red=True)
    lights_c.set_state(red=True)
    
    clear_screen()
    print("=" * 60)
    print("THREE-WAY TRAFFIC LIGHT SIMULATION (Paired Operation)")
    print("=" * 60)
    print("\nInitialization - All Red\n")
    print(f"Main road North (A): {lights_a.display()}")
    print(f"Main road South (B): {lights_b.display()}")
    print(f"Side road (C):       {lights_c.display()}")
    print("\nPress Ctrl+C to stop")
    print("=" * 60)
    sleep(2)
    
    try:
        cycle = 0
        while True:
            cycle += 1
            
            # Main road (A+B) gets green
            clear_screen()
            print("=" * 60)
            print(f"Cycle {cycle}: Main road (A+B) has priority")
            print("=" * 60)
            
            # Red+amber
            lights_a.set_state(red=True, amber=True)
            lights_b.set_state(red=True, amber=True)
            lights_c.set_state(red=True)
            print(f"\nMain road North (A): {lights_a.display()}")
            print(f"Main road South (B): {lights_b.display()}")
            print(f"Side road (C):       {lights_c.display()}")
            print("\nPhase: Main road preparing to go...")
            print("=" * 60)
            sleep(RED_AMBER_TIME)
            
            # Green
            lights_a.set_state(green=True)
            lights_b.set_state(green=True)
            lights_c.set_state(red=True)
            clear_screen()
            print("=" * 60)
            print(f"Cycle {cycle}: Main road (A+B) has priority - GO!")
            print("=" * 60)
            print(f"\nMain road North (A): {lights_a.display()}")
            print(f"Main road South (B): {lights_b.display()}")
            print(f"Side road (C):       {lights_c.display()}")
            print("=" * 60)
            sleep(MAIN_ROAD_GREEN)
            
            # Amber
            lights_a.set_state(amber=True)
            lights_b.set_state(amber=True)
            lights_c.set_state(red=True)
            clear_screen()
            print("=" * 60)
            print(f"Cycle {cycle}: Main road prepare to stop")
            print("=" * 60)
            print(f"\nMain road North (A): {lights_a.display()}")
            print(f"Main road South (B): {lights_b.display()}")
            print(f"Side road (C):       {lights_c.display()}")
            print("=" * 60)
            sleep(AMBER_TIME)
            
            # All red
            lights_a.set_state(red=True)
            lights_b.set_state(red=True)
            lights_c.set_state(red=True)
            clear_screen()
            print("=" * 60)
            print(f"Cycle {cycle}: Safety buffer - All Red")
            print("=" * 60)
            print(f"\nMain road North (A): {lights_a.display()}")
            print(f"Main road South (B): {lights_b.display()}")
            print(f"Side road (C):       {lights_c.display()}")
            print("=" * 60)
            sleep(ALL_RED_TIME)
            
            # Side road (C) gets green
            clear_screen()
            print("=" * 60)
            print(f"Cycle {cycle}: Side road (C) has priority")
            print("=" * 60)
            
            # Red+amber
            lights_a.set_state(red=True)
            lights_b.set_state(red=True)
            lights_c.set_state(red=True, amber=True)
            print(f"\nMain road North (A): {lights_a.display()}")
            print(f"Main road South (B): {lights_b.display()}")
            print(f"Side road (C):       {lights_c.display()}")
            print("\nPhase: Side road preparing to go...")
            print("=" * 60)
            sleep(RED_AMBER_TIME)
            
            # Green
            lights_a.set_state(red=True)
            lights_b.set_state(red=True)
            lights_c.set_state(green=True)
            clear_screen()
            print("=" * 60)
            print(f"Cycle {cycle}: Side road (C) has priority - GO!")
            print("=" * 60)
            print(f"\nMain road North (A): {lights_a.display()}")
            print(f"Main road South (B): {lights_b.display()}")
            print(f"Side road (C):       {lights_c.display()}")
            print("=" * 60)
            sleep(SIDE_ROAD_GREEN)
            
            # Amber
            lights_a.set_state(red=True)
            lights_b.set_state(red=True)
            lights_c.set_state(amber=True)
            clear_screen()
            print("=" * 60)
            print(f"Cycle {cycle}: Side road prepare to stop")
            print("=" * 60)
            print(f"\nMain road North (A): {lights_a.display()}")
            print(f"Main road South (B): {lights_b.display()}")
            print(f"Side road (C):       {lights_c.display()}")
            print("=" * 60)
            sleep(AMBER_TIME)
            
            # All red
            lights_a.set_state(red=True)
            lights_b.set_state(red=True)
            lights_c.set_state(red=True)
            clear_screen()
            print("=" * 60)
            print(f"Cycle {cycle}: Safety buffer - All Red")
            print("=" * 60)
            print(f"\nMain road North (A): {lights_a.display()}")
            print(f"Main road South (B): {lights_b.display()}")
            print(f"Side road (C):       {lights_c.display()}")
            print("=" * 60)
            sleep(ALL_RED_TIME)
    
    except KeyboardInterrupt:
        print("\n\nShutting down simulation...")
        lights_a.off()
        lights_b.off()
        lights_c.off()
        print("Simulation ended. Goodbye!")

def main():
    """
    Main menu for simulation selection.
    """
    print("=" * 60)
    print("TRAFFIC LIGHT SIMULATOR")
    print("=" * 60)
    print()
    print("Choose simulation type:")
    print("1. Two-way intersection")
    print("2. Three-way intersection (paired operation)")
    print("3. Exit")
    print()
    
    choice = input("Enter choice (1-3): ").strip()
    
    if choice == '1':
        two_way_simulation()
    elif choice == '2':
        three_way_simulation()
    elif choice == '3':
        print("Goodbye!")
        sys.exit(0)
    else:
        print("Invalid choice. Please run again.")
        sys.exit(1)

if __name__ == "__main__":
    main()
