#include <FastLED.h>

#define LED_PIN    2
#define LED_TYPE    WS2812B
#define COLOR_ORDER GRB
#define NUM_LEDS    70

CRGB leds[NUM_LEDS];


//PALETTE
DEFINE_GRADIENT_PALETTE( greenblue_gp ) { 
    0,    0,  194,  255,     //light blue
   46,    3,    0,  246,     //dark blue
  176,   55,  222,   70,     //bright green
  255,    0,  194,  255      //light blue
};

DEFINE_GRADIENT_PALETTE( orangepink_gp ) { 
    0,  255,  100,    0,     //orange
   90,  255,    0,  255,     //magenta
  150,  255,  100,    0,     //orange
  255,  255,  100,    0      //orange
};

DEFINE_GRADIENT_PALETTE( browngreen_gp ) { 
    0,    6,  255,    0,     //green
   71,    0,  255,  153,     //bluegreen
  122,  200,  200,  200,     //gray
  181,  110,   61,    6,     //brown
  255,    6,  255,    0      //green
};

FL_PROGMEM TProgmemRGBGradientPalettePtr const palettes[] = {
  greenblue_gp,
  orangepink_gp,
  browngreen_gp,
  Rainbow_gp
};
size_t const sz_palettes = sizeof(palettes) / sizeof(*palettes);

// two palettes to hold expanded gradient palettes, to be blended between
// set the B palette to the Rainbow palette, to fade in at power up
CRGBPalette16 palA, palB = palettes[sz_palettes - 1];

void setup() {
  FastLED.addLeds<LED_TYPE,LED_PIN,COLOR_ORDER>(leds, NUM_LEDS);
}


// return a random number which is different each time
uint8_t choose(uint8_t const choices) {
  static uint8_t last_choice = 0;
  uint8_t res;
  do {
    res = random8(choices);
  } while (res == last_choice);
  last_choice = res;
  return res;
}


void loop() {
  static uint8_t k1 = 0;        // the amount to blend [0-255]
  uint8_t const blendRate = 20; // How fast to blend.  Higher is slower.  [milliseconds]

  EVERY_N_MILLISECONDS(blendRate) {
    k1++; // advance the blend
    if (k1 == 0) {  // overflowed from 255 -> 0, so the blend is complete
      // copy B -> A and expand a different gradient palette into palette B
      palA = palB;
      uint8_t choice = choose(sz_palettes - 1); // -1 avoids picking Rainbow again
      palB = (TProgmemRGBGradientPalettePtr) FL_PGM_READ_WORD_NEAR(&palettes[choice]);
    }

    CRGB *led = leds;
    // for each strip
    for (uint8_t i = 0; i < 7; i++) {
      // select the two palette colours to be blended
      CRGB colA = ColorFromPalette(palA, i * 255 / 7);
      CRGB colB = ColorFromPalette(palB, i * 255 / 7);
      // use linear interpolation to fade between them
      colB = colA.lerp8(colB, k1);
      // set each of the 10 LEDs on this strip
      for (uint8_t j = 0; j < 10; j++)
        *led++ = colB;
    }
    FastLED.show();
  }
}