#include <IRremote.h>   //knihovna umoznujici dalkove ovladani
#include <avr/sleep.h>  //knihova umoznojici power-saving mode

//#include "IRremote2.h"

#define pinRemote 2     //definovani pinu IR diody

IRrecv dalkoveOvl(pinRemote);
decode_results vysledek;


int per = 4000;      //hodnota periody
int mode = 0;       //mod signalizace
int red_pin = 6;    //nastavení červeného pinu
int green_pin = 10; //nastavení zeleného pinu
int blue_pin = 9;   //nastavení modrého pinu
int brightness = 10;    //nastavení svítivosti, max 255
int color = 0;
bool powerDown = false;


void setup() {
  // put your setup code here, to run once:
  pinMode(red_pin, OUTPUT);   //- cervená LED
  pinMode(green_pin, OUTPUT);  //- zelena LED
  pinMode(blue_pin, OUTPUT);   //- modra LED
  Serial.begin(9600);
  
  dalkoveOvl.enableIRIn();
  
  attachInterrupt(digitalPinToInterrupt(pinRemote), interruptFuncion, INPUT_PULLUP );   //nastaveni preruseni na pin 2
  
}

void loop() {   //hlavní smyčka programu
  switch(mode){
    case 0:     //Isophase
      controlLED();   
      delay(per/2);
      RGB_color(0,0,0);   //bílá
      delay(per/2);
      break;
    case 1:   //Fixed
      controlLED();
      break;
    case 2:   //Flashing
      controlLED(); 
      delay(per/4);
      RGB_color(0,0,0);   //Off
      delay(3*per/4);
      break;
    case 3:   //Group flashing
      controlLED();
      delay(per/10);
      RGB_color(0,0,0);   //Off
      delay(per/5);
      controlLED();  //White
      delay(per/10);
      RGB_color(0,0,0);   //Off
      delay(3*per/5);
      break;
    case 4:   //Occulting
      RGB_color(0,0,0);   //Off
      delay(per/4);
      controlLED();   
      delay(3*per/4);
      break;
    case 5:   //Group occulting
      RGB_color(0,0,0);  //Off
      delay(per/10);
      controlLED();   
      delay(per/5);
      RGB_color(0,0,0);  //Off
      delay(per/10);
      controlLED();   
      delay(3*per/5);
      break;
    case 6:   //Quick Flashing
      controlLED();  //White
      delay(per/2);
      RGB_color(0,0,0);   //Off
      delay(per/2);
      break;
    case 7:   //Group Quick Flashing
      controlLED();
      delay(per/20);
      RGB_color(0,0,0);   //Off
      delay(per/20);
      controlLED();
      delay(per/20);
      RGB_color(0,0,0);   //Off
      delay(per/20);
      controlLED();
      delay(per/20);
      RGB_color(0,0,0);   //Off
      delay(7*(per/10));
      break;
    case 8:   //Alternate
      controlLED();   
      delay(per/2);
      RGB_color(brightness,brightness,brightness);   //bílá
      delay(per/2);
      break;
    case 9:   //group alternate
      RGB_color(0, 0, brightness); // Blue
      delay(per/3);
      RGB_color(0, 0, 0); //off
      delay(per/6);
      RGB_color(brightness, brightness, 0); // Yellow
      delay(per/3);
      RGB_color(0, 0, 0); //off
      delay(per/6);
      break;
  }
}

void RGB_color(int red_light_value, int green_light_value, int blue_light_value)
 {
  analogWrite(red_pin, red_light_value);
  analogWrite(green_pin, green_light_value);
  analogWrite(blue_pin, blue_light_value);
}


void interruptFuncion(){
  if (dalkoveOvl.decode(&vysledek)) {
      // pro zkoušení nového ovladače stačí odkomentovat
      // následující řádek a číst data po sériové lince
      Serial.println(vysledek.value, HEX);
  
      // volání podprogramu detekceKlaves pro
      // zjištění názvu klávesy
      detekceKlaves();
      // pokračování v detekci nových stisků
      dalkoveOvl.resume();
    }    
}

void detekceKlaves() {
  switch(vysledek.value) {
    // u každé stisknuté klávesy se vždy vypíše
    // její název po sériové lince
    case 0xFFA25D:  
      Serial.println("Stisknuto CH-");
      if(inRange(color,1, 3))
        color--;
      break;
    case 0xFF629D:  
      Serial.println("Stisknuto CH");
      color = 0;
      break;
    case 0xFFE21D:  
      Serial.println("Stisknuto CH+");
      if(inRange(color,0, 2))
        color++;
      break;
    case 0xFF22DD:  
      Serial.println("Stisknuto PREV");
       if(inRange(per,1000, 20000)){
        per -= 500;
        Serial.println(per);
      }
      break;
    case 0xFF02FD:  
      Serial.println("Stisknuto NEXT");
      if(inRange(per,1000, 19500)){
        per += 500;
        Serial.println(per);
      }
      break;
    case 0xFFC23D:  
      Serial.println("Stisknuto PLAY/PAUSE");
      if(powerDown){
        sleep_disable();
        powerDown = false;
        }
      else{
        power_down();
        }
      break;
    case 0xFFE01F:  
      Serial.println("Stisknuto VOL-");
      if(inRange(brightness,10, 255)){
        brightness -= 10;
        Serial.println(brightness);
      }
      break;
    case 0xFFA857:  
      Serial.println("Stisknuto VOL+");
      if(inRange(brightness,0, 245)){
        brightness += 10;
        Serial.println(brightness);
      }
      break;
    case 0xFF906F:  
      Serial.println("Stisknuto EQ");
      if(inRange(color,4, 6))
        color++;
      else
        color = 4;
      break;
    case 0xFF6897:  
      Serial.println("Stisknuto 0");
      Serial.println("Mode Isophase");
      mode = 0;
      per = 4000;
      break;
    case 0xFF9867:  
      Serial.println("Stisknuto 100+");
      break;
    case 0xFFB04F:  
      Serial.println("Stisknuto 200+");
      break;
    case 0xFF30CF:
    case 0xFF847B:  
      Serial.println("Stisknuto 1");
      Serial.println("Mode fixed");
      mode = 1;
      break;
    case 0xFF18E7:
    case 0xFF44BB:
      Serial.println("Stisknuto 2");
      Serial.println("Mode flashing");
      per = 4000;
      mode = 2;
      break;
    case 0xFF7A85:  
      Serial.println("Stisknuto 3");
      Serial.println("Mode group flashing");
      per = 10000;
      mode = 3;
      //per = 200;
      break;
    case 0xFF10EF:  
      Serial.println("Stisknuto 4");
      Serial.println("Mode occulting");
      mode = 4;
      per = 4000;
      break;
    case 0xFF38C7:  
      Serial.println("Stisknuto 5");
      Serial.println("Mode group occulting");
      per = 10000;
      mode = 5;
      break;
    case 0xFF5AA5:  
      Serial.println("Stisknuto 6");
      Serial.println("Mode quick light");
      per = 1000;
      mode = 6;
      break;
    case 0xFF42BD:  
      Serial.println("Stisknuto 7");
      Serial.println("Mode group quick light");
      per = 10000;
      mode = 7;
      break;
    case 0xFF4AB5:  
      Serial.println("Stisknuto 8");
      Serial.println("Mode alternate");
      per = 4000;
      mode = 8;
      break;
    case 0xFF52AD:  
      Serial.println("Stisknuto 9");
      Serial.println("Mode occulting alternate");
      per = 3000;
      mode = 9;
      break;
    default: 
      Serial.println("Stisknuta jina klavesa");
  }
}

void wakeUp(){      //funkce probuzení
  sleep_disable();  
  powerDown = false;
  detachInterrupt(digitalPinToInterrupt(2));   
  attachInterrupt(digitalPinToInterrupt(2), interruptFuncion, INPUT_PULLUP );
  }

void power_down() {
  sleep_enable();
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  RGB_color(0,0,0);   //Off
  powerDown = true;
  noInterrupts();
  attachInterrupt(digitalPinToInterrupt(2), wakeUp, LOW);   //nastavi na pin 2 probuzeni
  Serial.flush();
  interrupts();
  delay(1000);
  sleep_cpu();    //uspí CPU
  RGB_color(brightness,0,0);
  powerDown = false;
  }

void controlLED(){    //funkce na změnu barvy
  switch(color){
    case 0:   //White
      RGB_color(brightness, brightness, brightness);  //White
      break;
    case 1:   //Red 
      RGB_color(brightness, 0, 0); // Red 
      break;
    case 2:   //Green
      RGB_color(0, brightness, 0);   //Green
      break;
    case 3:   //Yellow
      RGB_color(brightness, brightness, 0); // Yellow
      break;
    case 4:   //Raspberry
      RGB_color(brightness, brightness, brightness/2); // Raspberry
      break;
    case 5:   //Cyan
      RGB_color(0, brightness, brightness); // Cyan
      break;
    case 6:   //Magenta
      RGB_color(brightness, 0, brightness); // Magenta
      break;
    case 7:   //Blue
      RGB_color(0, 0, brightness); // Blue
      break;
    default:
      RGB_color(brightness, brightness, brightness);  //White
      break;
    }
  }

bool inRange(int input,int minValue, int maxValue){     //pomocná funkce která vrátí jestli vstupní hodnota leží v rozsahu
  if((input >=minValue) && (input<= maxValue))
    return true;
  else
    return false;
  }
