#include <FastLED.h>

#define LED_PIN     8
#define NUM_LEDS    66
#define half_size    NUM_LEDS/2
#define quarter_size NUM_LEDS/4
#define half_sizef    NUM_LEDS/2.0
#define quarter_sizef NUM_LEDS/4.0
#define BRIGHTNESS  255
#define LED_TYPE    WS2812B
#define COLOR_ORDER GRB
CRGBArray<NUM_LEDS> leds;
CRGBSet LEFT (leds (0, NUM_LEDS/2-1));
CRGBSet RIGHT(leds (NUM_LEDS/2, NUM_LEDS-1));
CRGBSet L1 (LEFT (0, quarter_size));
CRGBSet L2 (LEFT (quarter_size, NUM_LEDS/2-1));
CRGBSet R1 (RIGHT (0, quarter_size));
CRGBSet R2 (RIGHT (quarter_size, NUM_LEDS/2-1));

struct CRGB * led_array[] = { LEFT, RIGHT };
struct CRGB * led_array1[] = { L1, L2, R1, R2 };

#define UPDATES_PER_SECOND 40

uint8_t gHue = 0;
int _BPM = 30;

void setup() {
    Serial.begin(115200);
    delay( 3000 ); // power-up safety delay
    FastLED.addLeds<LED_TYPE, 8, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
    FastLED.addLeds<LED_TYPE, 7, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
    FastLED.setBrightness(  BRIGHTNESS );
}


void loop()
{
    EVERY_N_MILLISECONDS(20){ gHue++; }
    tape_reel();
//    LEFT[0] = CRGB::Red;
//    LEFT[half_size-1] = CRGB::Green;
//    RIGHT[0] = CRGB::Blue;
//    RIGHT[half_size-1] = CRGB::Yellow;
    FastLED.show();
}

void tape_reel(){
    //fadeToBlackBy( leds, NUM_LEDS, 200);
    FastLED.clear();
    float b;
    static float spots = 1.0; static float incr = 0.005;
    for(float i = 0; i < spots; i++){
        float offset = half_size/spots;

        float _fractL = beat16(30)/65535.0;
        b = _fractL * half_size + i*offset;
        DrawPixels(b, 1.5, CHSV(gHue, 255, 255),  LEFT, half_size);

        float _fractR = beat16(29)/65535.0;
        b = (1.0f - _fractR) * half_size + i*offset;
        DrawPixels(b, 1.5, CHSV(gHue, 255, 255), RIGHT, half_size);
    }
    if(spots < 1){
        incr = 0.005;
    }
    if(spots > 8){
        incr = -0.005;
    }
    spots += incr;
}

CRGB ColorFraction(CRGB colorIn, float fraction){
    fraction = min(1.0f, fraction);
    return CRGB(colorIn).fadeToBlackBy(255 * (1.0f - fraction));
}

void DrawPixels(float fPos, float count, CRGB color, CRGB *led_base, uint8_t num_leds){
    // Calculate how much the first pixel will hold
    float availFirstPixel = 1.0f - (fPos - (long)(fPos));
    float amtFirstPixel = min(fmod(availFirstPixel, num_leds), count);
    float remaining = count;
    int iPos = fPos;

    // Blend (add) in the color of the first partial pixel

    if (remaining > 0.0f){
        led_base[iPos++ % num_leds] += ColorFraction(color, amtFirstPixel);
        remaining -= amtFirstPixel;
    }

    // Now draw any full pixels in the middle

    while (remaining > 1.0f){
        led_base[iPos++ % num_leds] += color;
        remaining--;
    }

    // Draw tail pixel, up to a single full pixel

    if (remaining > 0.0f){
        led_base[iPos % num_leds] += ColorFraction(color, remaining);
    }
}