#include <stdio.h>
#include <Arduino.h>
#include"timer-api.h"
#define L1_Pin 7
#define B1_Pin 4
#define L2_Pin 8
#define B2_Pin 3
#define B_dec 5
#define B_inc 6
#define Blue_Pin 9
#define Green_Pin 10
#define Red_Pin 11

byte lastButtonState;
byte ledState = LOW;
byte L2_State = LOW;
byte B_dec_lastState = LOW;
byte B_inc_lastState = LOW;
byte B2_LastState = LOW;

unsigned long lastTimeButtonChanged = millis(); 
unsigned long debounceDuration = 100;
int freq = 100;

static FILE stream;

void Task_1(void);
void Task_2(void);
void Task_3(void);
void Task_4(void);

#define rec_1 100
#define rec_2 100
#define rec_3 100
#define rec_4 100
#define rec_idle 2000

#define ofc_1 10
#define ofc_2 15
#define ofc_3 20
#define ofc_4 25
#define ofc_idle 30

int recCnt_1 = ofc_1;
int recCnt_2 = ofc_2;
int recCnt_3 = ofc_3;
int recCnt_4 = ofc_4;
int recCnt_idle = ofc_idle;

int serialPutChar(char ch, FILE *f) {
  Serial.write(ch);
  return ch;
}

int serialGetChar(FILE *f) {
  while (!Serial.available());
  return Serial.read();
}

void setup() {
    Serial.begin(9600);
    fdev_setup_stream(&stream, serialPutChar, serialGetChar, _FDEV_SETUP_RW);
    stdin = stdout = stdin = &stream;
    // freq=1Hz, period=1s
    timer_init_ISR_1KHz(TIMER_DEFAULT);

    pinMode(L1_Pin, OUTPUT);
    pinMode(L2_Pin, OUTPUT);
    pinMode(B1_Pin, INPUT);
    pinMode(B_inc, INPUT);
    pinMode(B_dec, INPUT);
    pinMode(Green_Pin, OUTPUT);
    pinMode(Blue_Pin, OUTPUT);
    pinMode(Red_Pin, OUTPUT);
    lastButtonState = digitalRead(B1_Pin);
}

void loop() {

  if(recCnt_1 <= 0){
    Task_1();
    recCnt_1 = rec_1;
  }
  if(recCnt_2 <= 0){
    Task_2();
    recCnt_2 = rec_2;
  }
  if(recCnt_3 <= 0){
    Task_3();
    recCnt_3 = rec_3;
  }
  if(recCnt_4 <= 0){
    Task_4();
    recCnt_4 = rec_4;
  }
  if(recCnt_idle <= 0){
    printf("LED State: ");
    if(ledState == LOW){
    printf("LOW\n");
    printf("Led Frequence: %d\n", freq);
    }
    else{
    printf("HIGH\n");
    }
    recCnt_idle = rec_idle;
  }

  
  

    // any code here: blocking or non-blocking
    // здесь любой код: блокирующий или неблокирующий
}

/**
 * Timer interrupt service routine, called with chosen period
 * @param timer - timer id
 */
/**
 * Процедура, вызываемая прерыванием по событию таймера с заданным периодом
 * @param timer - идентификатор таймера
 */
void timer_handle_interrupts(int timer) {
  recCnt_1--;
  recCnt_2--;
  recCnt_3--;
  recCnt_4--;
  recCnt_idle--;
}

void Task_1(void){
  if(millis() - lastTimeButtonChanged >= debounceDuration){
    byte buttonState = digitalRead(B1_Pin);
    if(buttonState != lastButtonState){
      lastTimeButtonChanged = millis();
      lastButtonState = buttonState;
      if(buttonState == LOW){
        setColor(255,0,0);
        if(ledState == HIGH){
          ledState = LOW;
        }
        else{
          ledState = HIGH;
        }
        digitalWrite(L1_Pin, ledState);
      }
    }
  }
}
void Task_2(void){
  static unsigned long LastBlinkTime = 0;
  if(ledState == LOW){
    unsigned long CurrentMillis = millis();
    if(CurrentMillis - LastBlinkTime >= freq){
      LastBlinkTime = CurrentMillis;
      if(L2_State == LOW){
        L2_State = HIGH;
      }else{
        L2_State = LOW;
      }
      digitalWrite(L2_Pin, L2_State);
    }
  }else{
    digitalWrite(L2_Pin, LOW);

  }
}
void Task_3(void){
  byte b_inc_state = digitalRead(B_inc);
  if(b_inc_state != B_inc_lastState){
    B_inc_lastState = b_inc_state;
    if(b_inc_state == LOW){
      setColor(0,255,0);
      freq = freq + 50;
    }
  }

  byte B_dec_state = digitalRead(B_dec);
  if(B_dec_state != B_dec_lastState){
    B_dec_state = B_dec_lastState;
    if(B_dec_state == LOW && freq > 0){
      setColor(0,0,255);
      freq = freq - 50;
    }
    if(freq == 0){
      printf("Frequncy limit !\n");
    }
  }
}

void Task_4(void){
  byte B2_state = digitalRead(B2_Pin);
  if(B2_state != B2_LastState){
    B2_LastState = B2_state;
    if(B2_state == LOW){
      setColor(255,255,0);
      digitalWrite(L1_Pin, HIGH);
      ledState = HIGH;
      freq = 100;
    }
  }
}

void setColor(int redValue, int greenValue,  int blueValue) {
  analogWrite(Red_Pin, redValue);
  analogWrite(Green_Pin,  greenValue);
  analogWrite(Blue_Pin, blueValue);
}