#define CLK 8
#define CLKE 4
#define DIO 7
#define DT 5
#define SW 6
#define FAST_ALGORITHM
#define MOSFET 9
#define BUZZER 10
#define BAT A0

#include "GyverEncoder.h"
#include "GyverTimers.h"
#include "GyverTM1637.h"

Encoder enc(CLKE, DT, SW);
GyverTM1637 disp(CLK, DIO);

volatile int minutes = 0;
volatile int seconds = 10;
volatile byte machinestate = 0;
boolean flag;
int batValue;
float voltage;
int percent;
byte end[4] = {_empty, _E, _n, _d};

void setup() {
  Serial.begin(9600);
  pinMode(A0,INPUT);
  Timer1.setFrequency(1);
  Timer1.enableISR(CHANNEL_B);
  enc.setType(TYPE2);
  enc.setTickMode(MANUAL);
  pinMode(MOSFET, OUTPUT);
  digitalWrite(MOSFET, LOW);
  disp.clear();
  disp.brightness(7);
  disp.point(1);
  disp.displayClock(minutes, seconds);
  tone(BUZZER, 500);
  delay(500);
  noTone(BUZZER);
}

void loop() {
  enc.tick();
  stateChange();
  battery();
  switch (machinestate) {
    case 0:
      if (enc.isRight())
      {
        encRight();
        disp.point(1);
        disp.displayClock(minutes, seconds);
      }
      else if (enc.isLeft())
      {
        encLeft();
        disp.point(1);
        disp.displayClock(minutes, seconds);
      }
  }
}

ISR(TIMER1_B) {
  switch (machinestate) {
    case 1:
      counter();
      disp.point(1);
      disp.displayClock(minutes, seconds);
  }
}

void counter() {
  digitalWrite(MOSFET, HIGH);
  if (seconds == 0) {
    if (minutes == 0) {
      exit;
    }
    else {
      seconds = 59;
      minutes --;
    }
  }
  else
    seconds --;
}

void stateChange() {
  if ((enc.isHolded()) && (machinestate == 0)) {
    tone(BUZZER, 700);
    delay(100);
    noTone(BUZZER);
    delay(100);
    tone(BUZZER, 800);
    delay(100);
    noTone(BUZZER);
    machinestate = 1;
  }
  else if ((machinestate == 1) && (minutes == 0) && (seconds == 0)) {
    machinestate = 3;
    digitalWrite(MOSFET, LOW);
    tone(BUZZER, 700);
    delay(100);
    tone(BUZZER, 500);
    delay(100);
    tone(BUZZER, 300);
    delay(100);
    noTone(BUZZER);
    delay(50);
    tone(BUZZER, 800);
    delay(400);
    noTone(BUZZER);
    disp.point(0);
    disp.twistByte(end, 50);
    delay(2000);
    machinestate = 0;
    minutes = 0;
    seconds = 10;
    disp.point(1);
    disp.displayClockScroll(minutes, seconds, 100);
  }
  else if (enc.isPress()) {
    if (machinestate == 1) {
      machinestate = 2;
      digitalWrite(MOSFET, LOW);
      tone(BUZZER, 300);
      delay(70);
      noTone(BUZZER);
    }
    else if (machinestate == 2) {
      machinestate = 1;
      tone(BUZZER, 900);
      delay(70);
      noTone(BUZZER);
      digitalWrite(MOSFET, HIGH);
    }
  }
  else if (machinestate == 2 ) {
    flag = !flag;
    disp.point(flag);
    delay(200);
  }
}

void encRight() {
  if (minutes == 0) {
    if (seconds <= 29) {
      seconds ++;
    }
    else if ((seconds >= 30) && (seconds <= 50)) {
      seconds += 5;
    }
    else if (seconds == 55) {
      minutes = 1;
      seconds = 0;
    }
  }
  else if ((minutes >= 1) && (minutes <= 4) && (seconds <= 40)) {
    seconds += 10;
  }
  else if ((minutes >= 1) && (minutes <= 4) && (seconds == 50)) {
    minutes ++;
    seconds = 0;
  }
  else if ((minutes >= 5) && (minutes <= 9) && (seconds == 0)) {
    seconds += 30;
  }
  else if ((minutes >= 5) && (minutes <= 9) && (seconds == 30)) {
    minutes ++;
    seconds = 0;
  }
  else if ((minutes >= 10) && (minutes <= 98)) {
    minutes ++;
  }
  else {
    exit;
  }
}

void encLeft() {
  if (minutes >= 11)
    minutes --;
  else if ((minutes <= 10) && (minutes >= 5)) {
    if ((minutes == 5) && (seconds == 0)) {
      minutes --;
      seconds = 50;
    }
    else if (seconds == 30) {
      seconds = 0;
    }
    else if (seconds == 0) {
      minutes --;
      seconds = 30;
    }
  }
  else if ((minutes <= 5) && (minutes >= 1)) {
    if ((minutes == 1) && (seconds == 0)) {
      minutes = 0;
      seconds = 55;
    }
    else if (seconds == 0) {
      seconds = 50;
      minutes --;
    }
    else {
      seconds -= 10;
    }
  }
  else if (minutes == 0)
  {
    if (seconds >= 35) {
      seconds -= 5;
    }
    else if ((seconds <= 30) && (seconds != 1)) {
      seconds --;
    }
    else if (seconds == 1) {
      seconds = 1;
    }
  }
}

void battery () {
  //  int batValue = analogRead(BAT);
  //  float voltage = sensorValue * (5.00 / 1023.00) * 2;
  float voltage = 4.2;
  if (voltage >= 4.2)
    percent == 100;
  else if (voltage >= 4.1 && voltage < 4.0)
    percent == 90;
  else if (voltage >= 4.0 && voltage < 3.9)
    percent == 80;
  else if (voltage >= 3.9 && voltage < 3.8)
    percent == 70;
  else if (voltage >= 3.8 && voltage < 3.7)
    percent == 60;
  else if (voltage >= 3.7 && voltage < 3.6)
    percent == 50;
  else if (voltage >= 3.6 && voltage < 3.5)
    percent == 40;
  else if (voltage >= 3.5 && voltage < 3.4)
    percent == 30;
  else if (voltage >= 3.4 && voltage < 3.3)
    percent == 20;
  else if (voltage >= 3.3)
    percent == 10;
  else if (voltage > 3.3)
    percent == 0;
  Serial.println(percent);
}
4-Digit Display