#include "SevSeg.h"
SevSeg sevseg;
int inc_brightness = A0;  //Light adjustment switch 1
int dec_brightness = A1;  //Light adjustment switch 2
int start_timer = A2;  //Start Timer PB
int reset_timer = A3;  //Reset Timer PB
int inc_time = A4;   //Increment countdown PB
int dec_time = A5;   //Decrement countdown PB
int alarmState = 13;  //Alarm control pin

bool timerRunning;  //Indicates if the timer is countingdown
long startTime = 0; //The initial time for the countdown
int brightness;   //The brightness level of the display

const long secInterval = 1000;
const long toneInterval = 500;
const long displayInterval = 150;
long prevTimerTime = 0;
long prevToneTime = 0;
long prevDisplayTime = 0;


void setup()
{
  //Setup input and output pins
  pinMode(inc_time, INPUT);
  pinMode(dec_time, INPUT);
  pinMode(start_timer, INPUT);
  pinMode(reset_timer, INPUT);
  pinMode(inc_brightness, INPUT);
  pinMode(dec_brightness, INPUT);
  pinMode(alarmState, OUTPUT);

  //7 Segment Display Setup
  byte numDigits = 4;
  byte digitPins[] = {2, 3, 4, 5};
  byte segmentPins[] = {6, 7, 8, 9, 10, 11, 12};
  bool resistorsOnSegments = false; // 'false' means resistors are on digit pins
  byte hardwareConfig = COMMON_ANODE; // See README.md for options
  bool updateWithDelays = false; // Default 'false' is Recommended
  bool leadingZeros = true; // Use 'true' if you'd like to keep the leading zeros
  bool disableDecPoint = true; // Use 'true' if your decimal point doesn't exist or isn't connected. Then, you only need to specify 7 segmentPins[]
  
  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments,
  updateWithDelays, leadingZeros, disableDecPoint);

  sevseg.setBrightness(0);
}


void displayTime(long usrTime)
{
  //Break usrTime into minutes and seconds
  int minute = 100 * (usrTime/60);
  int second = usrTime % 60;

  int countdownTime = minute + second;

  sevseg.setNumber(countdownTime,0);
  sevseg.refreshDisplay();
}


void adjustLight()
{
  //Increase or decrease brightness depending on user input
  if (digitalRead(inc_brightness) == HIGH && digitalRead(dec_brightness) == LOW
      && brightness < 100)
  {
        brightness += 100;
        delay(500);
  }   
  if (digitalRead(dec_brightness) == HIGH && digitalRead(inc_brightness) == LOW
      && brightness > -100)
  {
      brightness -= 100;
      delay(500);
  }
  sevseg.setBrightness(brightness);
  sevseg.refreshDisplay();
} 


int startTimer(long startTime)
{ 
  startTime++;
  while(startTime >= 0)
  {
    //Decrease countdown by 1 second per second
    timerRunning = 1;
    long currentTimerTime = millis();
    if(currentTimerTime - prevTimerTime >= secInterval)
      {
        startTime--;
        prevTimerTime = currentTimerTime;
      }

    long currentToneTime = millis();

    //Start beeping tone when countdown has 10 seconds remaining
    if(startTime <= 10 && startTime > 0)
    {
      if(currentToneTime - prevToneTime >= toneInterval)
      {

        if(digitalRead(alarmState) == HIGH)
          digitalWrite(alarmState, 0);
        else if(digitalRead(alarmState) == LOW)
          digitalWrite(alarmState, 1);
        
        prevToneTime = currentToneTime;
      }
    }

    //Start constant tone when countdown has 0 seconds remaining
    if(startTime == 0)
    {
      //Play alarm
      digitalWrite(alarmState, 1);
      timerRunning = 0;

      while(digitalRead(reset_timer) == LOW)
        displayTime(0);

      if(digitalRead(reset_timer) == HIGH && digitalRead(alarmState) == HIGH)   //Resets timer
      {
        timerRunning = 0;
        digitalWrite(alarmState, 0);    //Stop alarm
        delay(500);   //PB debouncer
        return 0;
      }
      
    }
    
    displayTime(startTime);
  }
  
}


void loop()
{
  //Allow user to adjust countdown time when timer has not started/is not running
  long currentDisplayTime = millis();
  if(timerRunning != 1 && (currentDisplayTime - prevDisplayTime) >= displayInterval)
  {
    if(digitalRead(inc_time) == HIGH && digitalRead(dec_time) == LOW
      && startTime < 600)
      {
        startTime++;
      }
    else if(digitalRead(inc_time) == LOW && digitalRead(dec_time) == HIGH
           && startTime > 0)
      {
        startTime--;
      }

    prevDisplayTime = currentDisplayTime;
    displayTime(startTime);   //Display the time onto 7Seg    
  }

  //Starts timer
  if(digitalRead(start_timer) == HIGH && timerRunning != 1)
  {
    startTimer(startTime);    //Start Timer
    delay(500);   //PB debouncer
  }

  //Allow user to adjust brightness of display when timer is not running
  if(timerRunning != 1)
    adjustLight();
  
}
