#define ledStripPinR 5
#define ledStripPinG 6
#define ledStripPinB 9

int currentLedR = 0;
int currentLedG = 0;
int currentLedB = 0;

int targetLedR = 0;
int targetLedG = 0;
int targetLedB = 0;

int fadeDelay = 5;

// Modes:
// 0 = Off
// 1 = Static
// 2 = Fade
// 3 = Dynamic
int currentMode = 2;

void handleLedStrip () {

  // Check if we need to handle target colors
  if (currentLedR == targetLedR && currentLedG == targetLedG && currentLedB == targetLedB) {
    return;
  }
   
  // Check which mode we are in, and change values based on that
  if (currentMode == 1) {
    // Static Mode
    analogWrite(ledStripPinR, targetLedR);
    analogWrite(ledStripPinG, targetLedG);
    analogWrite(ledStripPinB, targetLedB);
  }

  if (currentMode == 2) {
    // Fade Mode

    //
    // Red
    //
    
    // Target val is greater, add to current led value 
    if (targetLedR > currentLedR) {
      currentLedR = currentLedR + 1;
    }

    // Target val is smaller, remove from current led value 
    if (targetLedR < currentLedR) {
      currentLedR = currentLedR - 1;
    }

    //
    // Green
    //

    // Target val is greater, add to current led value 
    if (targetLedG > currentLedG) {
      currentLedG = currentLedG + 1;
    }

    // Target val is smaller, remove from current led value 
    if (targetLedG < currentLedG) {
      currentLedG = currentLedG - 1;
    }

    //
    // Blue
    //

    // Target val is greater, add to current led value 
    if (targetLedB > currentLedB) {
      currentLedB = currentLedB + 1;
    }

    // Target val is smaller, remove from current led value 
    if (targetLedB < currentLedB) {
      currentLedB = currentLedB - 1;
    }

    analogWrite(ledStripPinR, currentLedR);
    analogWrite(ledStripPinG, currentLedG);
    analogWrite(ledStripPinB, currentLedB);

    if (currentLedR == targetLedR && currentLedG == targetLedG && currentLedB == targetLedB) {
      char deviceUUID[10] = "34gr-54jf";
      char command[20] = "target_reached";
      char data[69] = "0";
      sendSerialCommand(deviceUUID, command, data);
    }

    delay(fadeDelay);
  }

}

void ledStripCommand(char* deviceUUID, char* command, char* data) {
  if (strcmp(command, "clear_color") == 0) {
    targetLedR = 0;
    targetLedG = 0;
    targetLedB = 0;
  }

  if (strcmp(command, "set_color") == 0) {
    setColor(data);
  }

  if (strcmp(command, "set_mode") == 0) {
    setMode(data);
  }

  if (strcmp(command, "set_mode") == 0) {
    setMode(data);
  }

  if (strcmp(command, "set_fade_delay") == 0) {
    setFadeDelay(data);
  }
}
 
void setColor(char* dataBuffer) {
  char * strtokIndex;
  char rValueRaw[4];
  char gValueRaw[4];
  char bValueRaw[4];
    
  // Get Red Value
  strtokIndex = strtok(dataBuffer, ",");
  strcpy(rValueRaw, strtokIndex);
  
  // Get Green Value
  strtokIndex = strtok(NULL, ",");
  strcpy(gValueRaw, strtokIndex);
  
  // Get Blue Value
  strtokIndex = strtok(NULL, ",");
  strcpy(bValueRaw, strtokIndex);
  
  targetLedR = atoi(rValueRaw);
  targetLedG = atoi(gValueRaw);
  targetLedB = atoi(bValueRaw);
}

void setMode(char* dataBuffer) {
  if (strcmp(dataBuffer, "static") == 0) {
    currentMode = 1;
  }
  
  if (strcmp(dataBuffer, "fade") == 0) {
    currentMode = 2;
  }
}

void setFadeDelay(char* dataBuffer) {
  fadeDelay = atoi(dataBuffer);
}

void initLedStrip() {
  
  // Define Pin Outputs
  pinMode(ledStripPinR, OUTPUT);
  pinMode(ledStripPinG, OUTPUT);
  pinMode(ledStripPinB, OUTPUT);

  // Write 0 to all rgbs
  analogWrite(ledStripPinR, 0);
  analogWrite(ledStripPinG, 0);
  analogWrite(ledStripPinB, 0);

  // Loop Each Color
  //

  // Red
  for (int colorIndex = 0; colorIndex < 256; colorIndex++) {
     analogWrite(ledStripPinR, colorIndex);
     delay(3);
  }

  for (int colorIndex = 255; colorIndex > -1; colorIndex--) {
     analogWrite(ledStripPinR, colorIndex);
     delay(3);
  }

  // Green
  for (int colorIndex = 0; colorIndex < 256; colorIndex++) {
     analogWrite(ledStripPinG, colorIndex);
     delay(3);
  }

  for (int colorIndex = 255; colorIndex > -1; colorIndex--) {
     analogWrite(ledStripPinG, colorIndex);
     delay(3);
  }

  // Blue
  for (int colorIndex = 0; colorIndex < 256; colorIndex++) {
     analogWrite(ledStripPinB, colorIndex);
     delay(3);
  }

  for (int colorIndex = 255; colorIndex > -1; colorIndex--) {
     analogWrite(ledStripPinB, colorIndex);
     delay(3);
  }

  // All
  for (int colorIndex = 0; colorIndex < 256; colorIndex++) {
     analogWrite(ledStripPinR, colorIndex);
     analogWrite(ledStripPinG, colorIndex);
     analogWrite(ledStripPinB, colorIndex);
     delay(3);
  }

  for (int colorIndex = 255; colorIndex > -1; colorIndex--) {
     analogWrite(ledStripPinR, colorIndex);
     analogWrite(ledStripPinG, colorIndex);
     analogWrite(ledStripPinB, colorIndex);
     delay(3);
  }
  
}
