// Gemma_Cat.ino
// Code for running on Gemma Cat - a repurposed cat deterrent turned into a mood light.
// based on NeoPixel library sample sketch byttoncycler.ino by Tony Dicola for Adafruit: 
// https://github.com/adafruit/Adafruit_NeoPixel/blob/master/examples/buttoncycler/buttoncycler.ino
// This project uses Adafruit's Gemma: https://www.adafruit.com/product/1222

#include <Adafruit_NeoPixel.h>

#define BUTTON_PIN   0    // Digital IO pin connected to the button.  This will be
                          // driven with a pull-up resistor so the switch should
                          // pull the pin to ground momentarily.  On a high -> low
                          // transition the button press logic will execute.

#define PIXEL_PIN    1    // Digital IO pin connected to the NeoPixels.

#define PIXELS 16
#define BRIGHTNESS 50

// Create the strip using Adafruit_NeoPixel()
// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_RGB     Pixels are wired for RGB bitstream
//   NEO_GRB     Pixels are wired for GRB bitstream, correct if colors are swapped upon testing
//   NEO_RGBW    Pixels are wired for RGBW bistream
//   NEO_KHZ400  400 kHz bitstream (e.g. FLORA pixels)
//   NEO_KHZ800  800 kHz bitstream (e.g. High Density LED strip), correct for neopixel stick
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXELS, PIXEL_PIN, NEO_GRBW + NEO_KHZ800);

bool newState = HIGH;
bool oldState = HIGH;
int showType = 1;
int RRed, RGreen, RBlue;
int NoOfShows = 7;

void setup()
{
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  strip.setBrightness(BRIGHTNESS);
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
}

void loop() 
{
  startShow(showType);
}

int WaitForButton()
{

  while (newState == HIGH)
  {
    newState = digitalRead(BUTTON_PIN);
    delay(50);  // wait here for bounce to subside
  }
  while (newState == LOW)
  {
    newState = digitalRead(BUTTON_PIN);
    delay(50);  // wait here for bounce to subside
  }
  showType++;
  if (showType > NoOfShows)
  {
    showType = 0;
  }
}

int GetButtonPress()
{
  int returnState = HIGH;
    newState = digitalRead(BUTTON_PIN);
    delay(50);  // wait here for bounce to subside
    if (newState == LOW)
    {
      returnState = LOW;
      showType++;
      if (showType > NoOfShows)
      {
        showType = 0;
      }  
    }
    while (newState == LOW)
    {
      newState = digitalRead(BUTTON_PIN);
      delay(50);  // wait here for bounce to subside
    }
    return returnState;
}
void startShow(int i)
{

  switch(i){
    case 0:
      RainbowCycle(50);  
      WaitForButton();
      break;
      
    case 1: 
      CreepyCat();  
      //WaitForButton();
      break;
      
    case 2:
      Rainbow(1);
      GetButtonPress();
      break;
        
    case 3: 
      NiteLite();
      WaitForButton();
      break;

    case 4: 
      AngryCat();  
      WaitForButton();
      break;
      
    case 5: 
      Light();  
      WaitForButton();
      break;

    case 6: 
      Rainbow(0);
      GetButtonPress();
      break;
      
    case 7: 
      RainbowCycle(10);  
      //WaitForButton();
      break;
  }
}

void Eyes(uint8_t Mode)
{
  switch(Mode){
    case 0:
      strip.setPixelColor(14, 0, 0, 0, 0);
      strip.setPixelColor(15, 0, 0, 0, 0);
      break;
    case 1:
      strip.setPixelColor(14, 0, 16, 6, 0);
      strip.setPixelColor(15, 0, 16, 6, 0);
      break;
    case 2:
      strip.setPixelColor(14, 0, 32, 12, 0);
      strip.setPixelColor(15, 0, 32, 12, 0);
      break;
    case 3:
      strip.setPixelColor(14, 255, 0, 0, 0);
      strip.setPixelColor(15, 255, 0, 0, 0);
      break;
  }
}


void Off() {
  uint16_t i;
  for(i=0; i<PIXELS-2; i++) {
    strip.setPixelColor(i, 0, 0, 0, 0);
  }
  Eyes(0);
  strip.show();
  //delay(wait);
}

void Rainbow(uint8_t Direction)
{
  uint16_t i;
  uint16_t j = PIXELS-2;
  for(i=0; i<PIXELS-2; i++)
  {
    j = (i + ((PIXELS-2)/2)) % (PIXELS-2);
    if (Direction == 0)
    {
      strip.setPixelColor(i, Wheel((i * 256 / (PIXELS-2)) & 255));
    }
    else
    {
      strip.setPixelColor(j, Wheel((i * 256 / (PIXELS-2)) & 255));
    }    
  }
  Eyes(1);
  strip.show();
  //delay(wait);
}

// Slightly different, this makes the rainbow equally distributed throughout
void RainbowCycle(uint8_t wait)
{
  uint16_t i, j;
  while (GetButtonPress() == LOW)
  {}  // wait here if the button is still depressed
  for(j=0; j<256; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< PIXELS-2; i++) 
    {
      strip.setPixelColor(i, Wheel(j));
    }
    Eyes(1);
    strip.show();
    delay(wait*3);
    if (GetButtonPress() == LOW)
    {
      break;
    }
  }
}

void NiteLite() 
{
  for(uint16_t i=0; i<PIXELS-2; i++)
  {
    strip.setPixelColor(i, strip.Color(32, 16, 0, 0) );
  }
  Eyes(0);
  strip.show();
}


void AngryCat() 
{
  for(uint16_t i=0; i<PIXELS-2; i++)
  {
    strip.setPixelColor(i, strip.Color(0, 0, 0, 0) );
  }
  Eyes(3);
  strip.show();
}


void Light() 
{
  for(uint16_t i=0; i<PIXELS-2; i++)
  {
    strip.setPixelColor(i, strip.Color(255, 255, 255, 255) );
  }
  Eyes(2);
  strip.show();
}

void CreepyCat() 
{
  for(uint16_t i=0; i<PIXELS-2; i++)
  {
    strip.setPixelColor(i, strip.Color(0, 0, 0, 0) );
  }
  Eyes(1);
  strip.show();
}

///////////////////////////////////////////////////////////////////////////////////////////


// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

uint8_t red(uint32_t c) {
  return (c >> 8);
}
uint8_t green(uint32_t c) {
  return (c >> 16);
}
uint8_t blue(uint32_t c) {
  return (c);
}
