void setup() {
	Serial.begin(9600);
}

int linearGuideLength = 100;

// A variable to determine if the system can receive configuration or not.
bool systemBusy = false;

// We will need some variables to store the data we will receive and parse.
String serialBuffer, commandSet, value;
int commandCode, flag = 0;
void loop() {
	while( Serial.available() ) {
		// Give the serialBuffer some millis to fill up.
		delay( 3 ); // 3 milliseconds are usually enough when operating at 16mhz
		if( Serial.available() > 0 ) {
			// Read the next available character into a local variable
			char c = Serial.read();
			// Append it to our buffer-string
			serialBuffer += c;
		}
	}

	if( serialBuffer.length() > 0 && !systemBusy ) {
		// First let's parse the commandSet, which is the first character of our buffer
		commandSet = serialBuffer.substring( 0, 1 );
		// In order to switch-case the commandset, we will need to convert it into a character.
		// There's probably a better way to do this, but this is how I've done it :)
		char set[12];
		commandSet.toCharArray( set, 12 );
		char type = set[0];

		// Next, we parse the command-code from the first word of our buffer.
		// Example: M100, the command-code in this part is "100"
		commandCode = serialBuffer.substring( 1, 4 ).toInt();

		// After parsing the command-code, we will need to parse the flag, which is used
		// to determine if we're getting or setting the value.
		// Defaults to always get ( flag = 0 )
		flag = serialBuffer.substring( 5, 6 ).toInt();
		
		// And finally, we will store the value into a string, 
		// which we will then use to cast into other types.
		// For the substring function, we will then pass in the entire length of the buffer,
		// which will give us the value until the line-terminator.
		value = serialBuffer.substring( 7, serialBuffer.length() );

		// Next up, we will switch-case the command-set "type", here we can setup different
		// prefixes for command-sets; for example M/m I will use to denote a configuration
		// and I will use G/g to denote a movement-instruction.
		// You can change the prefixes and/or add new ones as needed. 
		switch( type ) {
			case 'M':
			case 'm':
				interpretConfigCode( commandCode, flag, value );
				break;
			case 'G':
			case 'g':
				interpretMachineCode( commandCode, flag, value );
				break;
			default:
				Serial.print( "ERROR\n" );
				break;
		}
		// Next up, we will empty the buffer.
		serialBuffer = "";

	}

}

void interpretConfigCode( int commandCode, int flag, String value ) {
	switch( commandCode ) {
		case 100: {
			if( flag == 1 ) {
				// Set a value, for example linearGuideLength
				int newLength = value.toInt();
				linearGuideLength = newLength;
				Serial.print( "OK\n" );
			} else {
				// Return the value currently used
				Serial.print( "OK " );
				Serial.print( linearGuideLength );
				Serial.print( "\n" );
			}
			break;
		}
		default: {
			Serial.print( "UNKOWN\n");
			break;
		}
	}
}

void interpretMachineCode( int commandCode, int flag, String value ) {
	switch( commandCode ) {
		case 100: {
			// Do something.
		}
		default: {
			Serial.print( "UNKOWN\n");
			break;
		}
	}
}