#include <FastLED.h>//import library

#define LED_PIN     0

#define NUM_LEDS    15

#define BRIGHTNESS  60

#define LED_TYPE    WS2811

#define COLOR_ORDER GRB

CRGB leds[NUM_LEDS];//creates array of LEDS

#define UPDATES_PER_SECOND 100

CRGBPalette16 currentPalette;//current palette

void setup() {

    delay(100); // power-up safety delay

    FastLED.addLeds<NEOPIXEL, LED_PIN>(leds, NUM_LEDS);//adds LEDs to library

    FastLED.setBrightness(BRIGHTNESS);//sets brightness

    SetupUkrainianPalette();//sets up first program

}

void loop()

{    

    static byte startIndex = 0;//loops through palette

    static unsigned long timer = millis();//keeps time

    static byte counter = 0;//program counter

    startIndex++;//increase startIndex

    startIndex = (startIndex==16 && counter==3)?0:startIndex;//reset startIndex for 4th program

    if(millis()-timer>=7000){//if 7 seconds passed

      counter = (counter==3)?0:counter+1;//change program

      timer = millis();//reset time

      startIndex = 0;//reset startIndex

    }

    if(counter<=1){

       FillLEDsFromPaletteColors(startIndex, counter);//if the program is 1st or 2nd, run the palette

    }

    else if(counter==2){

      randomChoice();//run random color choice if 3rd program

    }

    else{

      wave(startIndex);//if 4th program, run the wave shape

    }

    FastLED.show();//update LEDs

    if(counter>1){

        FastLED.delay(300/counter);//delay for program 3 and 4

    }

    else{

      FastLED.delay(1000/UPDATES_PER_SECOND);//delay for program 1 and 2

    }

}

void FillLEDsFromPaletteColors(byte colorIndex, byte c)//code that runs for the 2 palette programs

{

    switch(c){//decides which program to run

    case 0:

      for( int i = 0; i < NUM_LEDS; i++) {

          leds[i] = ColorFromPalette(currentPalette, colorIndex);//scrolls through colors

          colorIndex += 4;//increments index for next LED so all LEDs are different

      }

    break;

    case 1:

    for( int i = 0; i < NUM_LEDS; i++) {

          leds[i] = ColorFromPalette(currentPalette, colorIndex);//all LEDs are the same

    }

     break;

    }

}

void SetupUkrainianPalette()//makes the Ukrainian Stripes Palette

{

    CRGB blue = CRGB::Blue;

    CRGB yellow  = CRGB::Yellow;

    currentPalette = CRGBPalette16(//creates palette pattern

                                   blue,  blue,  yellow,  yellow,

                                   blue, blue, yellow,  yellow,

                                   blue,  blue,  yellow,  yellow,

                                   blue, blue, yellow,  yellow );

}

void randomChoice(){

  for(int i = 0; i<NUM_LEDS; i++){

    leds[i] = (random(0, 2))?CRGB::Blue:CRGB::Yellow;//randomly assigns blue or yellow to LED

  }

}

void wave(byte si){

  if(si == 0){

    for(int i = 0; i<NUM_LEDS; i++){

      leds[i] = CRGB::Blue;//makes all LEDs blue

    }

  }

  if(si<8){

      leds[(NUM_LEDS-1)/2+si] = leds[(NUM_LEDS-1)/2-si] = CRGB::Yellow;//changes blue to yellow from inside of LED strip

  }

  else{

     leds[NUM_LEDS-1-(si-(NUM_LEDS+1)/2)] = leds[0+si-(NUM_LEDS+1)/2] = CRGB::Blue;//changes yellow to blue from outside to inside of LED strip

  }

}