# -*- coding: utf-8 -*-
import os
import sys
import termios
import tty
import select
import time

def main():
    """Main function to run the Computer Architecture slideshow."""
    
    # Check if running in an interactive terminal
    if not sys.stdin.isatty():
        print("Error: This script must be run in an interactive terminal.")
        sys.exit(1)

    # Lambda to clear the screen
    clear = lambda: os.system('clear')

    slides = [
        {
            "content": "Subject: Computer Architecture",
            "frames": [
r"""
   ______                            
  / ____/___  ____ ___  ____  __  __
 / /   / __ \/ __ `__ \/ __ \/ / / /
/ /___/ /_/ / / / / / / /_/ / /_/ / 
\____/\____/_/ /_/ /_/ .___/\__,_/  
                    /_/             
      
   The Blueprint of the Machine.
""",
r"""
   ______                            
  / ____/___  ____ ___  ____  __  __
 / /   / __ \/ __ `__ \/ __ \/ / / /
/ /___/ /_/ / / / / / / /_/ / /_/ / 
\____/\____/_/ /_/ /_/ .___/\__,_/  
   ______           /_/             
  / ____/___  ____ ___  ____  __  __
 / /   / __ \/ __ `__ \/ __ \/ / / /
   The Blueprint of the Machine.
""",
r"""
   ______                            
  / ____/___  ____ ___  ____  __  __
 / /   / __ \/ __ `__ \/ __ \/ / / /
/ /___/ /_/ / / / / / / /_/ / /_/ / 
\____/\____/_/ /_/ /_/ .___/\__,_/  
   ______           /_/             
  / ____/___  ____ ___  ____  __  __
 / /   / __ \/ __ `__ \/ __ \/ / / /
   The Blueprint of the Machine.
   [Initialize]
"""
            ]
        },
        {
            "content": """The Von Neumann Architecture
    - Proposed by John von Neumann in 1945.
    - Key Concept: Stored-Program Computer.
    - Instructions and Data are kept in the SAME memory (RAM).
    - Components: CPU (Control Unit + ALU), Memory, I/O.""",
            "frames": [
"""
      [  C P U  ]             [ M E M O R Y ]
    +-------------+           +-------------+
    | Control Unit|           | Instructions|
    |     ALU     |           |    Data     |
    +-------------+           +-------------+
           ^                         ^
           |                         |
           +----------+--------------+
                      |
                   [ I/O ]
""",
"""
      [  C P U  ]             [ M E M O R Y ]
    +-------------+           +-------------+
    | Control Unit| <=======> | Instructions|
    |     ALU     |           |    Data     |
    +-------------+           +-------------+
           ^                         ^
           |                         |
           +----------+--------------+
                      |
                   [ I/O ]
""",
"""
      [  C P U  ]             [ M E M O R Y ]
    +-------------+           +-------------+
    | Control Unit|           | Instructions|
    |     ALU     | <=======> |    Data     |
    +-------------+           +-------------+
           ^                         ^
           |                         |
           +----------+--------------+
                      |
                   [ I/O ]
"""
            ]
        },
        {
            "content": """The System Bus: The Highway
    - How components talk to each other.
    - Address Bus: "Where are we looking?" (CPU -> RAM)
    - Data Bus: "Here is the information." (Bi-directional)
    - Control Bus: "Read or Write?" (CPU -> RAM)""",
            "frames": [
"""
    CPU  |                     |  RAM
    +----+ Address Bus (Loc)   +----+
    |    | ==================> |    |
    |    |                     |    |
    |    | Data Bus (Payload)  |    |
    |    | ==================> |    |
    +----+                     +----+
""",
"""
    CPU  |                     |  RAM
    +----+ Address Bus (Loc)   +----+
    |    | ==================> |    |
    |    |                     |    |
    |    | Data Bus (Payload)  |    |
    |    |        <==========  |    |
    +----+                     +----+
""",
"""
    CPU  |                     |  RAM
    +----+ Address Bus (Loc)   +----+
    |    |        <==========  |    |
    |    |                     |    |
    |    | Data Bus (Payload)  |    |
    |    | ==================> |    |
    +----+                     +----+
"""
            ]
        },
        {
            "content": """The Machine Cycle (Fetch-Decode-Execute)
    1. Fetch: Get instruction from RAM.
    2. Decode: Control Unit figures out what to do.
    3. Execute: ALU calculates the result.
    4. Store: Write result back to memory.""",
            "frames": [
"""
    Step 1: FETCH
    +-------+                 +-------------+
    |  CPU  |    << LOAD <<   | RAM: [0101] |
    |       |                 | (ADD 1 + 1) |
    +-------+                 +-------------+
""",
"""
    Step 2: DECODE
    +-------+                 +-------------+
    |  CU   |  [Thinking...]  | RAM: [0101] |
    | "ADD" |                 |             |
    +-------+                 +-------------+
""",
"""
    Step 3: EXECUTE
    +-------+                 +-------------+
    |  ALU  |   1 + 1 = 2     | RAM: [0101] |
    | [CALC]|                 |             |
    +-------+                 +-------------+
""",
"""
    Step 4: STORE
    +-------+                 +-------------+
    |  CPU  |   >> SAVE >>    | RAM: [0002] |
    | (2)   |                 | (Result)    |
    +-------+                 +-------------+
"""
            ]
        }
    ]

    navigations = "Press 'n' to move to the next slide"
    animation_delay = 0.8

    for slide in slides:
        move_to_next_slide = False
        while not move_to_next_slide:
            for frame in slide["frames"]:
                clear()
                print(slide["content"])
                print(frame)
                print(navigations)

                user_input = read_input_with_timeout(animation_delay)
                
                if user_input == 'n':
                    move_to_next_slide = True
                    break
    
    clear()
    print("Presentation Finished.")

def read_input_with_timeout(timeout):
    """Waits for a single character of input for a given timeout period."""
    fd = sys.stdin.fileno()
    old_settings = termios.tcgetattr(fd)
    try:
        tty.setcbreak(sys.stdin.fileno())
        # Check if there is input available
        if select.select([sys.stdin], [], [], timeout) == ([sys.stdin], [], []):
            return sys.stdin.read(1)
    finally:
        # Restore terminal settings
        termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
    return None

if __name__ == "__main__":
    main()
