void setup() {
  // Initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  waitForSerialConnection();
  
  Serial.println("Starting Examples...");
  
  // Call the example functions
  simpleConditionExample();
  waitForKeystroke();

  conditionWithElseExample();
  waitForKeystroke();

  multipleConditionsExample();
  waitForKeystroke();

  forLoopExample();
  waitForKeystroke();

  switchStatementExample();
  waitForKeystroke();

  Serial.println("All examples complete!");
}

void loop() {
  // Print a message to show that the loop function is running
  Serial.println("loop() function running");
  delay(1000); // Wait for 1 second before repeating
}

/**
 * Waits for the serial connection to be established.
 */
void waitForSerialConnection() {
  Serial.println("Initializing Serial Connection...");
  int attempts = 0;
  const int maxAttempts = 10;
  const int delayTime = 500; // milliseconds

  // Wait for serial connection or timeout after maxAttempts
  while (!Serial && attempts < maxAttempts) {
    attempts++;
    delay(delayTime); // Wait before retrying
  }

  // Check if serial connection was successful
  if (Serial) {
    Serial.println("Serial port connected.");
  } else {
    Serial.println("Failed to connect to the serial port. Check your connection.");
    while (true) {
      // Infinite loop to halt the program as serial connection failed
    }
  }
}

/**
 * Waits for a keystroke from the user to continue.
 */
void waitForKeystroke() {
  Serial.println("Press any key to continue...");
  while (Serial.available() == 0) {
    // Wait for user input
  }
  while (Serial.available() > 0) {
    Serial.read(); // Clear the buffer
  }
  Serial.println(); // Print a new line for better readability
}

/**
 * Demonstrates a simple condition.
 */
void simpleConditionExample() {
  Serial.println("Simple Condition Example");

  int value = 10;
  if (value > 5) {
    Serial.println("Value is greater than 5");
  }

  Serial.println("Simple Condition Example End");
}

/**
 * Demonstrates a condition with an else statement.
 */
void conditionWithElseExample() {
  Serial.println("Condition with Else Example");

  int value = 3;
  if (value > 5) {
    Serial.println("Value is greater than 5");
  } else {
    Serial.println("Value is 5 or less");
  }

  Serial.println("Condition with Else Example End");
}

/**
 * Demonstrates multiple conditions.
 */
void multipleConditionsExample() {
  Serial.println("Multiple Conditions Example");

  int value = 5;
  if (value > 5) {
    Serial.println("Value is greater than 5");
  } else if (value == 5) {
    Serial.println("Value is exactly 5");
  } else {
    Serial.println("Value is less than 5");
  }

  Serial.println("Multiple Conditions Example End");
}

/**
 * Demonstrates a loop using a while loop to simulate a for loop.
 */
void forLoopExample() {
  Serial.println("For Loop Example");

  int limit = 5;
  int i = 0;
  while (i < limit) {
    if (i == 2) {
      Serial.println("i is 2");
    } else {
      Serial.print("i is ");
      Serial.println(i);
    }
    i++;
  }

  Serial.println("For Loop Example End");
}

/**
 * Demonstrates a switch-like structure using if-else statements.
 */
void switchStatementExample() {
  Serial.println("Switch Statement Example");

  int expression = 2;
  if (expression == 1) {
    Serial.println("Expression is 1");
  } else if (expression == 2) {
    Serial.println("Expression is 2");
  } else if (expression == 3) {
    Serial.println("Expression is 3");
  } else {
    Serial.println("Expression is something else");
  }

  Serial.println("Switch Statement Example End");
}