// we ❤️ wokwi.com

#include <FastLED.h>
#include <avr/pgmspace.h>

#define NUM_LEDS (/*w*/ 5 * 16 + 4 * 12 + 2 * 10 + 2 * 13 \
                  /*o*/ + 64 + 56 \
                  /*k*/ + 16 + 4 * 10  + 4 * 12 \
                  /*w*/ + 2 * 22 + 6 * 20 \
                  /*i*/ + 2 * 18 + 16)
CRGB leds[NUM_LEDS];

void setup() {
  FastLED.setCorrection(UncorrectedColor);
  FastLED.setTemperature(UncorrectedTemperature);
  FastLED.addLeds<WS2812B, 2, GRB>(&leds[0], 174);    // w
  FastLED.addLeds<WS2812B, 3, GRB>(&leds[174], 120);  // o
  FastLED.addLeds<WS2812B, 4, GRB>(&leds[294], 104);  // k
  FastLED.addLeds<WS2812B, 5, GRB>(&leds[398], 164);  // w
  FastLED.addLeds<WS2812B, 6, GRB>(&leds[562], 52);   // i
}

struct Feature {
  uint16_t start;
  int8_t length;
};

const Feature features[] PROGMEM = {
  // W
  {0, 12+16+12+2},    // up the LHS of left stroke of W, around ring1, back down RHS, 2 dots of ring2
  {56, 10},           // up the LHS shallow centre stroke
  {72, 6},            // up from join of LHS of the steep centre stroke
  {78, 16},           // around ring3
  {94, 12},           // down RHS of steep centre
  {106, 2},           // 2 dots around ring4
  {132, 13},          // up the LHS of right stroke
  {145, 16},          // around ring5
  {161, 13},          // down the RHS of right stroke
  {108, 14},          // remainder of ring4
  {66, 6},            // up to join of LHS of the steep centre stroke
  {122, 10},          // down RHS of shallow centre stroke
  {42, 14},           // around the remainder of ring2
  // o
  {174, 64},          // clockwise around outer ring
  {238, -56},         // anti-clockwise around inner ring
  // k
  {294, 3},           // 3 dots around ring
  {310, -10},         // up LHS of top vert
  {320, -10},         // down RHS of top vert
  {297, 3},           // 3 more dots of ring
  {330, -12},         // up LHS of top right
  {342, -12},         // down RHS of top right
  {300, 4},           // 4 more dots of ring
  {354, 12},          // down RHS of bottom right
  {366, 12},          // up LHS of bottom right
  {304, 4},           // 4 more dots of ring
  {378, -10},         // down RHS of bottom vert
  {388, -10},         // up LHS of bottom vert
  {308, 2},           // last 2 dots of ring
  // w (max length is 127, so I split it into two)
  {398, 102}, {500, 62},
  // i
  {562, 52},
};

void loop() {
  static uint16_t frame;
  uint16_t total = -frame++;
  uint8_t hue = frame;
  for (uint8_t featno = 0; featno < sizeof(features) / sizeof(features[0]); featno++) {
    int8_t length = pgm_read_byte_near(&features[featno].length);
    uint16_t ledno = pgm_read_word_near(&features[featno].start);
    int8_t step = 1;
    if (length < 0) {
      length = -length;
      ledno += length - 1;
      step = -1;
    }
    while (length--) {
      if (total++ % 32 == 0) {
        leds[ledno] = CHSV(hue, 255, 255);
        hue += 4;
      } else {
        fadeToBlackBy(&leds[ledno], 1, 8);
        // leds[ledno] = CRGB::Black;
      }
      ledno += step;
    }
  }
  FastLED.show();
  delay(10);
}