#include <FastLED.h>

// Count of how many LEDs we have
#define LEDS_PER_FAN        12
#define LEDS_PER_AIO        9
#define LEDS_PER_STRIP      30
#define LED_TOTAL_NUM       (LEDS_PER_FAN * 2 + LEDS_PER_AIO + LEDS_PER_STRIP)

#define BRIGHTNESS      255      // 255 is full brightness, 128 is half
#define MIN_BRIGHTNESS  8        // watch the power!
#define MAX_BRIGHTNESS  255      // watch the power!


CRGB leds[LED_TOTAL_NUM] = {0}; // Allocate an array for how many LEDs there are

CRGBPalette16 purplePalette = CRGBPalette16 (

  CRGB::Teal,
  CRGB::Purple,
  CRGB::Blue,
  CRGB::Teal,

  CRGB::Purple,
  CRGB::Teal,
  CRGB::Blue,
  CRGB::Purple,

  CRGB::Blue,
  CRGB::DarkViolet,
  CRGB::Teal,
  CRGB::DarkViolet,

  CRGB::Purple,
  CRGB::Blue,
  CRGB::Teal,
  CRGB::DarkViolet

  );
  

CRGBPalette16 purplePalette2 = CRGBPalette16 (

  CRGB::Teal,
  CRGB::Purple,
  CRGB::Blue,
  CRGB::DarkViolet,

  CRGB::Teal,
  CRGB::Blue,
  CRGB::Blue,
  CRGB::Blue,

  CRGB::Teal,
  CRGB::Purple,
  CRGB::Blue,
  CRGB::DarkViolet,

  CRGB::Teal,
  CRGB::Purple,
  CRGB::Blue,
  CRGB::DarkViolet

  );

uint8_t paletteIndex = 0;

// Mapping the LED # to order from bottom of fan to top
static const int FanPixelsVertical[LED_TOTAL_NUM] = {
  6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, // Bottom fan
  18, 17, 19, 16, 20, 15, 21, 14, 22, 13, 23, 12, // Top fan
  30, 31, 29, 23, 28, 24, 27, 25, 26, // AIO
  32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61
};


// Setting up the initial state ==> Set all lights to make sure all are working as expected
void setup() {
  // Assign pin 3, 5, 6 and 9 as LED singal pins
  FastLED.addLeds<NEOPIXEL, 3>(leds, 0, LEDS_PER_FAN); // Pin 3 = Bottom fan front
  FastLED.addLeds<NEOPIXEL, 5>(leds, LEDS_PER_FAN, LEDS_PER_FAN); // Pin 5 = Top fan front
  FastLED.addLeds<NEOPIXEL, 6>(leds, LEDS_PER_FAN*2, LEDS_PER_AIO); // Pin 6 = AIO RGB
  FastLED.addLeds<NEOPIXEL, 9>(leds, LED_TOTAL_NUM - LEDS_PER_STRIP, LEDS_PER_STRIP); // Pin 9 = RGB strips

  FastLED.clear(); // Wipe the lights to start
  FastLED.show();
  FastLED.setBrightness( BRIGHTNESS );

  delay(1000); // Power-up safety delay

  // On wakeup, loops through and fills in from bottom fan -> top -> AIO -> strips
  int index = 0;
  for(int i = 0; i < LED_TOTAL_NUM; i++) {
    index = FanPixelsVertical[i];
    leds[index] = ColorFromPalette(purplePalette, index * 255 / LED_TOTAL_NUM);

    // Resets the palette for climbing effect
    /*if(paletteIndex < 15)
      paletteIndex++;
    if(index == 24)
      paletteIndex = 0;*/
      
    FastLED.show();
    delay(25);
  }
}


// This action will be performed (intended to be an infinite loop)
void loop() {
  // ****** START ROTATING PURPLE/BLUE PATTERN ****************************************************

  EVERY_N_MILLISECONDS(150) {
    paletteIndex++;
    fill_palette(leds, LED_TOTAL_NUM, paletteIndex, 255 / LED_TOTAL_NUM, purplePalette, 255, LINEARBLEND);
    FastLED.show();
  }

  // ****** END ROTATING PURPLE/BLUE PATTERN ******************************************************
}