#include "SPI.h"
#include "Wire.h"
#include "Adafruit_GFX.h"
//#include "Adafruit_SSD1306.h"
#include "Adafruit_ILI9341.h"

#include "RTClib.h"

/* oled 0.96
#define SCREEN_WIDTH 128 // OLED display width, in pixels
//#define SCREEN_HEIGHT 64 // OLED display height, in pixels

#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
*/
RTC_DS1307 rtc;

//ILI9341
#define TFT_DC 2
#define TFT_CS 33
Adafruit_ILI9341 display = Adafruit_ILI9341(TFT_CS, TFT_DC);

#define UP_BUTTON 14
#define DWN_BUTTON 26
#define MN_BUTTON 12
#define PL_BUTTON 27
#define BCK_BUTTON 13
#define FWD_BUTTON 25
//#define ALARM 2

String hours,mins,clocktxt;
int menu,pos,mSteps,hSteps,page,temp,minutes,startMin = 0;

int stepCount = 1;
int stepCount2 = 1;
int dataSelector = 0;
int currCount = 0;

int currStepMin,currStepTemp = 0;
int stepMin[6];
int stepTemp[6];
//int step4Min,step4Temp = 0;
//int step5Min,step5Temp = 0;
//int step6Min,step6Temp = 0;

int upVal, dwnVal, mnVal, plVal, bckVal, fwdVal;

const float BETA = 3950; // should match the Beta Coefficient of the thermistor
float celsius;

long startTime = 0;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

  analogReadResolution(10);
  pinMode(15,INPUT);

  //pinMode(ALARM, OUTPUT);

  pinMode(UP_BUTTON, INPUT_PULLUP);
  pinMode(DWN_BUTTON, INPUT_PULLUP);
  pinMode(MN_BUTTON, INPUT_PULLUP);
  pinMode(PL_BUTTON, INPUT_PULLUP);
  pinMode(BCK_BUTTON, INPUT_PULLUP);
  pinMode(FWD_BUTTON, INPUT_PULLUP);
  rtc.begin();
  //rtc.adjust(DateTime(2023, 02, 21, 11, 8, 00));
   // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  /*if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
    Serial.println(F("ILI9341 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }*/
  display.begin();
  //DateTime now = rtc.now();
  //startMin = now.minute();
  //header();
 
  //refresh();
  delay(2000);
  //display.clearDisplay();
}

int upState, dwnState, mnState, plState, bckState, fwdState = HIGH; 

void loop() {
  // put your main code here, to run repeatedly:

  int analogValue = analogRead(15);
  celsius = 1 / (log(1 / (1023. / analogValue - 1)) / BETA + 1.0 / 298.15) - 273.15;

  upVal = digitalRead((UP_BUTTON));
  dwnVal = digitalRead((DWN_BUTTON));
  mnVal = digitalRead((MN_BUTTON));
  plVal = digitalRead((PL_BUTTON));
  bckVal = digitalRead((BCK_BUTTON));
  fwdVal = digitalRead((FWD_BUTTON));
  
  switch (menu){
    case 0:
      //decrease positions
      if (upState != upVal){
        upState = upVal;
        if (upVal == LOW){
          if (pos > 0){
            pos--;
          }
          else{
            pos = 3;
          }
        }
        refresh();
      }
      //increase positions
      if (dwnState != dwnVal){
        dwnState = dwnVal;
        if (dwnVal == LOW){
          if (pos < 3){
            pos++;
          }
          else{
            pos = 0;
          }
        }
        refresh();
      }

      //check selection
      if (fwdState != fwdVal){
        fwdState = fwdVal;
        if (fwdVal == LOW){
          menu = pos+1;
        }
        refresh();
      }

      //move curssor
      switch (pos){
        
        case 0:
          header();
          display.setCursor(37,11);  display.print ("Main Menu");
          display.setCursor(5,20);  display.print (">Create receip");
          display.setCursor(5,29);  display.print (" Select receip");
          display.setCursor(5,38);  display.print (" Boil+Hopping");
          display.setCursor(5,47);  display.print (" Boil only");
          //refresh();
        break;

        case 1:
          header();
          display.setCursor(37,11);  display.print ("Main Menu");
          display.setCursor(5,20);  display.print (" Create receip");
          display.setCursor(5,29);  display.print (">Select receip");
          display.setCursor(5,38);  display.print (" Boil+Hopping");
          display.setCursor(5,47);  display.print (" Boil only");
          //refresh();
        break;

         case 2:
          header();
          display.setCursor(37,11);  display.print ("Main Menu");
          display.setCursor(5,20);  display.print (" Create receip");
          display.setCursor(5,29);  display.print (" Select receip");
          display.setCursor(5,38);  display.print (">Boil+Hopping");
          display.setCursor(5,47);  display.print (" Boil only");
          //refresh();
        break;

        case 3:
          header();
          display.setCursor(37,11);  display.print ("Main Menu");
          display.setCursor(5,20);  display.print (" Create receip");
          display.setCursor(5,29);  display.print (" Select receip");
          display.setCursor(5,38);  display.print (" Boil+Hopping");
          display.setCursor(5,47);  display.print (">Boil only");
          //refresh();
        break;
      }
    break;//end of menu 0 - Main menu

    case 1:
      display.setTextSize(1);
      display.setTextColor(ILI9341_WHITE);
      display.setCursor(22,0);  display.print("Mashing");
      display.drawLine (0,9,128,9, ILI9341_WHITE);
      //display.setCursor(37,11);  display.print ("Mashing");
      
      switch (page){
        case 0:
          //display.setCursor(37,11);  display.print ("Mashing");
          display.setCursor(0,20);  display.print ("Enter steps ...");
          display.setCursor(90,20);  display.print (mSteps);
          display.drawLine (0,29,128,29, ILI9341_WHITE);
          //selecting mashing mSteps
          if (plState != plVal){
            plState = plVal;
            if (plVal == LOW){
              if (mSteps < 6){
                mSteps++;
              }else{
                mSteps = 0;
              }
            }
          }
          if (mnState != mnVal){
            mnState = mnVal;
            if (mnVal == LOW){
              if (mSteps > 0){
                mSteps--;
              }else{
                mSteps = 6;
              }
            }
          }

          //check selection
          if (fwdState != fwdVal){
            fwdState = fwdVal;
            if (fwdVal == LOW && mSteps > 0){
              page++;
            }
          }
        break;//end of page case 0 - enter speps for mashing
        case 1:
          if (stepCount < mSteps+1){
            if (currCount != stepCount){
              currStepTemp = 0;
              currStepMin = 0;
              currCount = stepCount;
            }
            display.setCursor(0,20);  display.print ("On step:");
            display.setCursor(90,20);  display.print (stepCount);
            display.drawLine (0,29,128,29, ILI9341_WHITE);
            display.drawLine (0,63,128,63, ILI9341_WHITE);

            //decrease positions
            if (upState != upVal){
              upState = upVal;
              if (upVal == LOW){
                if (dataSelector == 0){
                  dataSelector = 1;
                }
                else{
                  dataSelector = 0;
                }
              }
            }
            //increase positions
            if (dwnState != dwnVal){
              dwnState = dwnVal;
              if (dwnVal == LOW){
                if (dataSelector == 0){
                  dataSelector = 1;
                }
                else{
                  dataSelector = 0;
                }
              }
            }
            switch (dataSelector){
              //adjust temp
              case 0:
                display.setCursor(0,31);  display.print (">Temperature ...");
                display.setCursor(100,31);  display.print (currStepTemp);
                display.setCursor(0,40);  display.print (" Minutes ...");
                display.setCursor(100,40);  display.print (currStepMin);
                if (plState != plVal){
                  plState = plVal;
                  if (plVal == LOW){
                    if ( currStepTemp < 80){
                      currStepTemp++;
                    }
                    else{
                      currStepTemp = 0;
                    }
                  }
                }
                if (mnState != mnVal){
                  mnState = mnVal;
                  if (mnVal == LOW){
                    if (currStepTemp > 0){
                      currStepTemp--;
                    }
                    else{
                      currStepTemp = 80;
                    }
                  }
                }
              break;
              case 1:
                display.setCursor(0,31);  display.print (" Temperature ...");
                display.setCursor(100,31);  display.print (currStepTemp);
                display.setCursor(0,40);  display.print (">Minutes ...");
                display.setCursor(100,40);  display.print (currStepMin);
                if (plState != plVal){
                  plState = plVal;
                  if (plVal == LOW){
                    if ( currStepMin < 180){
                      currStepMin++;
                    }
                    else{
                      currStepMin = 0;
                    }
                  }
                }
                if (mnState != mnVal){
                  mnState = mnVal;
                  if (mnVal == LOW){
                    if (currStepMin > 0){
                      currStepMin--;
                    }
                    else{
                      currStepMin = 180;
                    }
                  }
                }
              break;
            }
            //check selection
            if (fwdState != fwdVal){
              fwdState = fwdVal;
              if (fwdVal == LOW && stepCount <=6){
                if (currStepTemp != 0 && currStepMin != 0){
                  stepTemp[stepCount-1] = currStepTemp;
                  stepMin[stepCount-1] = currStepMin;
                  stepCount++;
                }
              }
            }
          }//sent to hopping page
          else{
            page++;
          }
        break;//end of page case 1 - mashing mSteps
        case 2:
          //dataSelector = 0;
          //display.setCursor(37,11);  display.print ("Mashing");
          display.setCursor(0,20);  display.print ("Ready?");
          display.drawLine (0,29,128,29, ILI9341_WHITE);
          //decrease positions
            if (upState != upVal){
              upState = upVal;
              if (upVal == LOW){
                if (dataSelector == 0){
                  dataSelector = 1;
                }
                else{
                  dataSelector = 0;
                }
              }
            }
            //increase positions
            if (dwnState != dwnVal){
              dwnState = dwnVal;
              if (dwnVal == LOW){
                if (dataSelector == 0){
                  dataSelector = 1;
                }
                else{
                  dataSelector = 0;
                }
              }
            }
            switch (dataSelector){
              //adjust temp
              case 0:
                display.setCursor(0,31);  display.print (">Save&Mash");
                display.setCursor(0,40);  display.print (" Mash");
              break;
              case 1:
                display.setCursor(0,31);  display.print (" Save&Mash");
                display.setCursor(0,40);  display.print (">Mash");
              break;
            }
            //check selection
            if (fwdState != fwdVal){
              fwdState = fwdVal;
              if (fwdVal == LOW){
                if (dataSelector == 0){
                  //save receip on SD card.....
                  page++;
                }
                else{
                  //DateTime now = rtc.now();
                  startTime = millis();
                  //startMin = now.minute();
                  page++;
                }      
              }
            }
        break;//end of page case 2 - Choose save or booil
        case 3:
          calcMinutes();
          if (minutes != 0 && minutes == stepMin[stepCount2-1]){
            minutes = 0;
            stepCount2++;
          }
          //if (celsius > stepTemp[stepCount2-1]){
            //digitalWrite(ALARM, HIGH);
          //}
          //display.setCursor(37,11);  display.print ("Mashing");
          if (stepMin[stepCount2-1] != 0 && stepTemp[stepCount2-1] != 0){
            display.setCursor(0,11); display.print ("Curr. step:");
            display.setCursor(70,11); display.print (stepCount2);
            display.setCursor(0,20); display.print ("Set temp:");
            display.setCursor(70,20); display.print (stepTemp[stepCount2-1]);
            display.setCursor(0,29); display.print ("Curr. temp:");
            display.setCursor(70,29); display.print (celsius);
            display.setCursor(0,38); display.print ("Set time:");
            display.setCursor(70,38); display.print (stepMin[stepCount2-1]);
            display.setCursor(0,47); display.print ("Elasped:");
            display.setCursor(70,47); display.print (minutes);
          }
          else{
            display.setCursor(0,47); display.print ("Elasped:");
            display.setCursor(70,47); display.print (minutes);
            delay(1000);
            display.setCursor(10,20); display.print ("Mashing over.");
            delay(2000);
            reset();
            //ESP.restart();
            //return;
          }
        break;
      }
      //refresh();
    break;//end of menu 1 - create receip
    //refresh();
  }

}
//header
void header()
{
  display.setTextSize(1);
  display.setTextColor(ILI9341_WHITE);
  display.setCursor(35,0);  display.print("Homebrewer");
  display.drawLine (0,9,128,9, ILI9341_WHITE);
}

void refresh()
{
  //display.clrScr();
  //delay(00);
  display.fillScreen(ILI9341_BLACK);
  display.setCursor(0,0);
}

void showClock(){
  hours = mins = clocktxt = "";
  DateTime now = rtc.now();
  hours = String(now.hour());
  if (now.minute() < 10){
    mins = "0"+ String(now.minute());
  }else{
    mins = String(now.minute());
  }
  clocktxt = hours+":"+mins;
  //display.clearDisplay();
  display.setCursor(35, 20);
  display.setTextColor(ILI9341_WHITE);
  display.setTextSize(2);
  display.println(clocktxt);
}

void calcMinutes(){
  //hours = mins = clocktxt = "";
  //DateTime now = rtc.now();
  long timeNow = millis();
  //if (startMin != now.minute()){
  if (timeNow >= (startTime+60000)){
    startTime = timeNow;
    minutes++;
  }
}

void reset(){
  menu,pos,mSteps,hSteps,page,temp,minutes,startMin = 0;

  stepCount = 1;
  stepCount2 = 1;
  dataSelector = 0;
  currCount = 0;

  currStepMin,currStepTemp = 0;
  memset(stepMin, 0, sizeof(stepMin));
  memset(stepTemp, 0, sizeof(stepTemp));
  //stepMin[6];
  //stepTemp[6];
  upState, dwnState, mnState, plState, bckState, fwdState = HIGH;
  celsius = 0 ;
}
GND5VSDASCLSQWRTCDS1307+