#include <Arduino.h>

// Union for storing different types of command data
union Data {
  int toInt;
  float toFloat;
  char toChar;
  String* toString;  // Use pointer for String
};

// Enum for data types
enum DataType {
  INT,
  FLOAT,
  CHAR,
  STRING
};

// Struct to relate commands to functions and data types
struct CommandFunc {
  char command;
  void (*function)(Data);
  DataType type;
};

// Function to handle integer commands
void handleCommandInt(Data value) {
  Serial.print("Integer value: ");
  Serial.println(value.toInt);
}

// Function to handle float commands
void handleCommandFloat(Data value) {
  Serial.print("Float value: ");
  Serial.println(value.toFloat, 3);  // 3 decimal places
}

// Function to handle char commands
void handleCommandChar(Data value) {
  Serial.print("Char value: ");
  Serial.println(value.toChar);
}

// Function to handle string commands
void handleCommandString(Data value) {
  Serial.print("String value: ");
  Serial.println(*value.toString);
}

// Array of commands
CommandFunc commands[] = {
  {'A', handleCommandInt, INT},
  {'B', handleCommandFloat, FLOAT},
  {'C', handleCommandChar, CHAR},
  {'D', handleCommandString, STRING}
};

const int numberOfCommands = sizeof(commands) / sizeof(commands[0]);

void setup() {
  Serial.begin(9600);
  Serial.println("Initializing...");
}

// Function to process commands
void processCommand(const char* command, const String& valueString) {
  for (int i = 0; i < numberOfCommands; ++i) {
    if (commands[i].command == *command) {
      Data data;
      switch (commands[i].type) {
        case INT:
          data.toInt = valueString.toInt();
          break;
        case FLOAT:
          data.toFloat = valueString.toFloat();
          break;
        case CHAR:
          data.toChar = valueString.charAt(0);
          break;
        case STRING:
          data.toString = &valueString; // Just points to valueString
          break;
      }
      commands[i].function(data);
      return;
    }
  }

  Serial.print("Invalid command: ");
  Serial.println(*command);
}

void loop() {
  static String buffer;
  while (Serial.available()) {
    char ch = Serial.read();
    if (ch == '\n' || ch == '\r') {
      if (buffer.length() > 1) {
        processCommand(&buffer[0], buffer.substring(2));
      }
      buffer = "";
    } else {
      buffer += ch;
    }
  }
}