#include <FastLED.h>


#define SENSOR_START 2   // пин датчика движения
#define SENSOR_END 3     // пин датчика движения
#define LED_PIN     4    // пин ленты
#define COUNT_STEPS   10 // количество ступенек
#define LED_STEP  20  // лампочек на ступеньке
#define LED_TYPE    WS2812B //тип ленты
#define COLOR_ORDER GRB  //порядок цветов
#define CUSTOM_BRIGHT 100  // ручная яркость
#define TIMEOUT 5           // секунд, таймаут выключения ступенек после срабатывания одного из датчиков движения 
#define NUMLEDS COUNT_STEPS*LED_STEP // кол-во светодиодов
#define SPEED 500 // скорость переключения



struct Step {
  byte led_amount; //количество чипов в ступеньке
  byte status_step; //статус ступеньки(0-выключена,1включяется,2-включена,3-выключается)
  byte num_animation; //номер кадра анимации
  uint16_t night_mode_bitmask;// маска
  uint16_t start_chip;// номер начального чипа в ступеньке вычесляется програмно
};
// описание всех ступенек с возможностью подсветки ЛЮБЫХ ступенек в ночном режиме
Step steps[COUNT_STEPS] = {
  { 20, 0, 0, 0b0100100100, 0}, // первая ступенька(20 чипов,0-выключена,0-кадр анимацыи, 0b0100100100100100 - маска,начальный чип заполним потом
  { 20, 0, 0, 0b0100100100 },
  { 20, 0, 0, 0b0100100100 },
  { 20, 0, 0, 0b0100100100 },
  { 20, 0, 0, 0b0100100100 },
  { 20, 0, 0, 0b0100100100 },
  { 20, 0, 0, 0b0100100100 },
  { 20, 0, 0, 0b0100100100 },
  { 20, 0, 0, 0b0100100100 },
  { 20, 0, 0, 0b0100100100 }
};
CRGB leds[NUMLEDS];    // буфер ленты
CRGB ON = CRGB::Red;  // цвет включения
CRGB OF = CRGB::Black;  // цвет выключения
// ==== удобные макросы ====================================================
#define FOR_i(from, to) for (int i = (from); i < (to); i++)
#define FOR_j(from, to) for (int j = (from); j < (to); j++)
#define FOR_k(from, to) for (int k = (from); k > (to); k--)
#define ANIMATE_TM(x) \
  static uint32_t Tmr=0;\
  bool flag = millis() - Tmr >= (x);\
  if (flag)Tmr += (x);\
  if (flag)
 
//===========================
bool M_stat = 0;// ----------глобальнве переменные
int effSpeed;
int8_t effectDirection;
byte curBright = CUSTOM_BRIGHT;

byte effectCounter;
uint32_t timeoutCounter;
bool TIMEstat = false;
byte poslednyi;
// bool systemOffState;


struct PirSensor {  //--------------датчик
  int8_t effectDirection;
  int8_t pin;
  bool lastState;
  CRGB cvet;
  byte zag_tuh;
  uint32_t time; //загорается или тухнет или 0 ничего не делает
};
PirSensor startPirSensor = { 1, SENSOR_START, false, OF, false, millis()};
PirSensor endPirSensor = { -1, SENSOR_END, false, OF, false, millis()};
//--------------------------------------------------
// CRGBPalette16 firePalette;

void setup() {
  Serial.begin(9600);
  FastLED.addLeds< LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUMLEDS);
  avtonum_startled();// автоматически находим и проставляем стартовый чип на каждой ступеньке
  FastLED.clear();
  FastLED.show();
}
void loop() {
  if(!startPirSensor.lastState)handlePirSensor(&startPirSensor); //опрашивается
  if(!endPirSensor.lastState)handlePirSensor(&endPirSensor); //опрашивается
  ANIMATE_TM(SPEED)  anim(); //опрашивается
  if (TIMEstat) handleTimeout();


}

void anim_start() {
  static int step = 0;
  if(startPirSensor.lastState){
    step = 0;;startPirSensor.cvet = ON;
    startPirSensor.lastState=false;startPirSensor.zag_tuh = 2;
    // Serial.println("начало start") ;
    }
  // Serial.println(step) ;
  FOR_i(0, step + 1) {
    FOR_j(steps[i].start_chip, steps[i].start_chip + steps[i].led_amount) {
      leds[j] = startPirSensor.cvet;
      // Serial.print(j);
    }

    // Serial.println() ;
  }
 
  if (step == COUNT_STEPS - 1){ 
    if( startPirSensor.zag_tuh==2) {
    step = 0;
    startPirSensor.lastState = false;
    startPirSensor.zag_tuh = 1;
    startPirSensor.cvet = OF;
    TIMEstat = true;
    timeoutCounter = millis();
  //  Serial.println("конец start") ;
   }
   if( startPirSensor.zag_tuh==1) { 
    startPirSensor.lastState = false;
    startPirSensor.zag_tuh = 0;
  }
  } else {
    
    step += 1;
  }
}

void anim_end() {
  
  static int step = COUNT_STEPS - 1;
  if(endPirSensor.lastState){
    step = COUNT_STEPS - 1;endPirSensor.cvet = ON;
    endPirSensor.lastState=false;endPirSensor.zag_tuh = 2;
    //  Serial.println("начало end") ;
    }
  // Serial.println(step) ;
  FOR_k(COUNT_STEPS - 1, step - 1) {
    FOR_j(steps[k].start_chip, steps[k].start_chip + steps[k].led_amount) {
      leds[j] = endPirSensor.cvet;
      // Serial.print(j);
    }

    // Serial.println() ;
  }

  if (step == 0){ 
    if( endPirSensor.zag_tuh==2) {
    step = COUNT_STEPS - 1;
    endPirSensor.lastState = false;
    endPirSensor.zag_tuh = 1;
    endPirSensor.cvet = OF;
    TIMEstat = true;
    timeoutCounter = millis();
  //  Serial.println("конец end") ;
   }
   if( endPirSensor.zag_tuh==1) { 
    endPirSensor.lastState = false;
    endPirSensor.zag_tuh = 0;
  }
   }else {
    
    step -= 1;
  }
}

void anim() {
  
  // Serial.println(startPirSensor.lastState) ;
  // if (startPirSensor.lastState ) {
    // Serial.print("крутим анимацыю") ;
    // Serial.println(2) ;
    if(startPirSensor.zag_tuh>0)anim_start();
  // }
  // if (endPirSensor.lastState ) {
    // Serial.print("крутим анимацыю") ;
    // Serial.println(3) ;
    if(endPirSensor.zag_tuh>0)anim_end();
  // }
  FastLED.show();

}


// void nightLight() {
//   Serial.print(0);
//   FastLED.clear();
//   FastLED.show();
//   Serial.println("выключаем");
//   return;

// }


void handleTimeout() {// таймер
  if (millis() - timeoutCounter >= (TIMEOUT * 1000)) {
    TIMEstat = false;
    if (poslednyi == 2) {
      startPirSensor.lastState = false;// выключаем
      startPirSensor.zag_tuh = 1;
    }
    if (poslednyi == 3) {
      endPirSensor.lastState = false;// выключаем
      endPirSensor.zag_tuh = 1;
    }
  }
}
void handlePirSensor(PirSensor * sensor) { //прослушивание сенсора

  //  Serial.println("опрашиваем датчик");
  int newState = digitalRead(sensor->pin);
  if (newState) {
    // Serial.print(newState);
    // Serial.print("сработал");
    // Serial.println(sensor->pin);

  
    if (sensor->zag_tuh<2 && millis()-sensor->time>1100){sensor->lastState = newState; sensor->cvet = ON;
    sensor->zag_tuh=2; sensor->time= millis();
    // Serial.print("загарается-");Serial.println(sensor->pin);
    }
    
    poslednyi = sensor->pin;
    
    TIMEstat = false;
    // Serial.println(newState);


  }

}
void avtonum_startled() {
  FOR_i(1, COUNT_STEPS) {
    steps[i].start_chip = steps[i - 1].start_chip + steps[i - 1].led_amount;
    // Serial.print(steps[i].start_chip) ;
  }
  // Serial.println();
}