#include <FastLED.h>

#define LED_PIN 3
#define NUM_LEDS 272
#define LED_TYPE WS2812
#define COLOR_ORDER GRB
#define BRIGHTNESS 255
#define UPDATES_PER_SECOND 100

CRGB leds[NUM_LEDS];
CRGB color_white = CRGB::White;
CRGB color_pupil = CRGB::Black;
CRGB color_iris = CRGB::Aqua;
CRGB color_lids = CRGB::LightSalmon;
CRGB colors[] = {color_lids, color_pupil};

struct PixelSet
{
    int count;
    int *pixels;
};

const PixelSet PupilCenter = {2, (int[]){240, 271}};
const PixelSet PupilLinks = {6, (int[]){218, 231, 240, 240, 255, 271}};
const PixelSet PupilLinks2 = {6, (int[]){159, 169, 216, 233, 257, 270}};
const PixelSet PupilLinks3 = {6, (int[]){156, 171, 218, 232, 259, 268}};
const PixelSet PupilLinks4 = {8, (int[]){73, 83, 156, 171, 220, 231, 261, 266}};
const PixelSet PupilLinks5 = {6, (int[]){71, 85, 157, 170, 221, 230}};
const PixelSet PupilRechts = {6, (int[]){190, 203, 240, 256, 271, 271}};
const PixelSet PupilRechts2 = {6, (int[]){119, 129, 188, 205, 241, 254}};
const PixelSet PupilRechts3 = {6, (int[]){116, 131, 190, 204, 243, 252}};
const PixelSet PupilRechts4 = {8, (int[]){21, 31, 116, 131, 192, 203, 245, 250}};
const PixelSet PupilRechts5 = {6, (int[]){19, 33, 117, 130, 193, 202}};
const PixelSet PupilLinksBoven = {6, (int[]){225, 238, 259, 271, 240, 244}};
const PixelSet PupilLinksBoven2 = {10, (int[]){169, 179, 223, 239, 184, 184, 261, 271, 240, 242}};
const PixelSet PupilLinksBoven3 = {6, (int[]){166, 181, 225, 240, 263, 271}};
const PixelSet PupilLinksBoven4 = {8, (int[]){86, 96, 166, 181, 227, 238, 265, 270}};
const PixelSet PupilLinksBoven5 = {6, (int[]){84, 98, 167, 180, 228, 237}};

const PixelSet IrisCenter = {2, (int[]){184, 239}};

const PixelSet Eyelids1 = {6, (int[]){0, 10, 41, 62, 93, 103}};
const PixelSet Eyelids2 = {10, (int[]){0, 14, 37, 66, 137, 150, 89, 110, 177, 183}};
const PixelSet Eyelids3 = {12, (int[]){0, 17, 86, 113, 174, 183, 34, 69, 132, 155, 207, 216}};
const PixelSet Eyelids4 = {14, (int[]){0, 20, 33, 72, 83, 118, 129, 158, 169, 191, 204, 219, 232, 239}};
const PixelSet Open = {0};
const PixelSet Closed = {2, (int[]){0, 271}};

struct PixelSets
{
    PixelSet iris;
    PixelSet pupil;
    PixelSet eyelids;
};

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

void blink(int timeout)
{
    anim2({PupilCenter, Eyelids1}, 10);
    anim2({PupilCenter, Eyelids2}, 10);
    anim2({PupilCenter, Eyelids3}, 10);
    anim2({PupilCenter, Eyelids4}, 10);
    anim2({PupilCenter, Closed}, 10);
    anim2({PupilCenter, Eyelids4}, 10);
    anim2({PupilCenter, Eyelids3}, 10);
    anim2({PupilCenter, Eyelids2}, 10);
    anim2({PupilCenter, Eyelids1}, 10);
    delay(timeout);
}

void squint(int timeout)
{
    anim2({PupilCenter, Eyelids1}, 20);
    anim2({PupilCenter, Eyelids2}, 70);
    anim2({PupilCenter, Eyelids3}, 700);
    anim2({PupilCenter, Eyelids2}, 70);
    anim2({PupilCenter, Eyelids1}, 30);
    anim2({PupilCenter, Eyelids2}, 10);
    delay(timeout);
}

void lookleft(int timeout)
{
    anim2({PupilLinks, Eyelids2}, 20);
    anim2({PupilLinks2, Eyelids2}, 20);
    anim2({PupilLinks3, Eyelids2}, 20);
    anim2({PupilLinks4, Eyelids2}, 20);
    anim2({PupilLinks5, Eyelids2}, 20);
    anim2({PupilLinks4, Eyelids2}, 20);
    anim2({PupilLinks3, Eyelids2}, 20);
    anim2({PupilLinks2, Eyelids2}, 20);
    anim2({PupilLinks, Eyelids2}, 20);
    anim2({PupilCenter, Eyelids2}, 10);
    delay(timeout);
}

void lookright(int timeout)
{
    anim2({PupilRechts, Eyelids2}, 20);
    anim2({PupilRechts2, Eyelids2}, 20);
    anim2({PupilRechts3, Eyelids2}, 20);
    anim2({PupilRechts4, Eyelids2}, 20);
    anim2({PupilRechts5, Eyelids2}, 20);
    anim2({PupilRechts4, Eyelids2}, 20);
    anim2({PupilRechts3, Eyelids2}, 20);
    anim2({PupilRechts2, Eyelids2}, 20);
    anim2({PupilRechts, Eyelids2}, 20);
    anim2({PupilCenter, Eyelids2}, 10);
    delay(timeout);
}

void looksee(int timeout){
    // open, wait, then lef, back, and then up
    anim2({PupilCenter, Eyelids2}, 1000);
    anim2({PupilLinks, Eyelids2},  100);
    anim2({PupilLinks2, Eyelids2}, 100);
    anim2({PupilLinks3, Eyelids2}, 300);
    anim2({PupilLinksBoven, Eyelids2}, 50);
    anim2({PupilLinksBoven2, Eyelids2}, 50);
    anim2({PupilLinksBoven3, Eyelids1}, 50);
    anim2({PupilLinksBoven4, Open}, 50);
    anim2({PupilLinksBoven5, Open}, 200);
    anim2({PupilLinksBoven4, Eyelids1}, 50);
    anim2({PupilLinksBoven3, Eyelids1}, 50);
    anim2({PupilLinksBoven2, Eyelids2}, 50);
    anim2({PupilLinksBoven, Eyelids2}, 50);
    anim2({PupilLinks3, Eyelids2}, 50);
    anim2({PupilLinks2, Eyelids2}, 50);
    anim2({PupilLinks, Eyelids2}, 50);
    anim2({PupilCenter, Eyelids2}, 10);
    delay(timeout);
}


void loop()
{
    anim2({PupilCenter, Open}, 2000);
    blink(500);
    blink(0);
    blink(1500);
    squint(1000);
    lookleft(0);
    lookright(0);
    delay(100);
    looksee(2000);
}

void anim2(PixelSets sets, int timeout)
{
    for (int pixnr = 0; pixnr < 272; pixnr++)
    {
        leds[pixnr] = color_white;
    }

    PixelSet list[] = {sets.pupil, sets.iris, sets.eyelids};
    for (int setnr = 0; setnr < 2; setnr ++)
    {
        PixelSet pixelset = list[setnr];
        for (int i = 0; i < pixelset.count; i += 2)
        {
            for (int pixnr = pixelset.pixels[i]; pixnr <= pixelset.pixels[i + 1]; pixnr++)
            {
                //     // set RGB of pixels[pixnr]
                leds[pixnr] = colors[setnr];
            }
        }
    }

    FastLED.show();
    delay(timeout);
}