/**************************************************************************

 **************************************************************************/

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define LOAD_BUTTON true

#if LOAD_BUTTON==true
  #include "OneButton.h"
#endif

///////////
//BUTTONS
const int TIME_PIN = 27;
//const int TIME_PIN = 13;
const int tonepin = 12;

OneButton time_button(TIME_PIN, true);

/////////
//Screen
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

////////////
//storage
#define STORAGE_SIZE  126  //126 // more than 60 causes issues with arduino UNO (120 OK for ESP) IDEAL WOULD BE 126 for tick every 0.5 seconds!
float storage[STORAGE_SIZE];
int ticks;

//////////////
//STopwatch
long startTime ;                    // start time for stop watch
long elapsedTime = 0;                  // elapsed time for stop watch            
int seconds1 = elapsedTime / 1000L;;
int subseconds1 = (elapsedTime-(seconds1*1000))/100;
bool stopwatch = false;


////
//TODO: WAAGE!

long int iter;

void setup() {
  Serial.begin(9600);
  setup_display();


  time_button.attachClick(singleclick);
  time_button.attachLongPressStart(longclick);


}

void loop() {
  time_button.tick();
  iter ++;

  display.clearDisplay();
  
  display.setTextSize(2); // Draw 2X-scale text
  display.setTextColor(WHITE);

  draw_seperator_line();


  ////STOPWATCH-MODE////////////////////////////////////////////////
  if (stopwatch == true) {
    run_stopwatch();

    //STORE DATA
    if ((subseconds1+1) % 5 == 0){ticks++;} // in total: 126(+) ticks for whole duration!
    storage[ticks] = random(1,100); //TODO: ADD CURRENT WEIGHT!


    if (seconds1 > 30){
      end_stopwatch();
    }
  } //END STOPWATCH-MODE 
  else {
  ////NOT-Stopwatch MODE  
    display_time();
    
    
  }


  display_weight(iter*1.1);
  display.display(); //needs to happen at the end
}



///////////
///////////
//FUNCTIONS

////
//DISPLAY

void setup_display(){
  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64 /////beim ESP: 0x3C, bei Arduino UNO: 0x3D)) { 
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }
  display.display();
}

void display_weight(float current_weight){
  display.setCursor(60, 44);
  display.println(current_weight,1);
}

void display_time(){
    display.setCursor(10, 5); //zeile:1 (erste) spalte: 6
    if (seconds1<10){display.print("0");} //print leading 0 for seconds
    display.print(seconds1);
    display.print(".");
    display.print(subseconds1);
}

void draw_seperator_line(){
  display.drawLine(0,63,126,0,WHITE); //128*64
  display.drawLine(0,64,128,0,WHITE); //128*64
  display.drawLine(0,65,130,0,WHITE); //128*64
}

///////
///BUTTONS

void singleclick() {
  Serial.println("Single Cick"); 
  
  if (stopwatch == false){ //to start stopwatch
    prep_stopwatch(); //Start Stopwatch --> DONE via bool!
    //TODO: TARE
  } else { stopwatch = false;}  //if already running: Stop the stoppwatch and leave time!

} // singleclick

void longclick() {
  Serial.println("LONG Cick");
  //plot data
  plot_data();
  delay(10000);

} //doubleclick


////////
//STOPWATCH

void prep_stopwatch() {
  Serial.println("prep stopwatch");
  //display.clearDisplay();
  display.setCursor(10, 5);
  for (int i = 0; i < 8; i++) { 
    uint16_t temp_x = SCREEN_WIDTH/8;
    display.fillRect(i*temp_x, 0, temp_x, SCREEN_HEIGHT, WHITE);
    delay(250);
    display.display();
  }
  stopwatch = true; // set for stopwatch mode
  // set parameters to ZERO
  startTime = millis();
  elapsedTime = 0; 
  seconds1=0;
  subseconds1=0;
}



//run stopwatch routine
void run_stopwatch(){
    
    //get elapsed time
    elapsedTime =   millis() - startTime; 
    seconds1 = elapsedTime / 1000L;
    subseconds1 = (elapsedTime-(seconds1*1000))/100;

    display_time();

    //piepen
    if (seconds1 == 25 and subseconds1 <2){ //beep
      tone(tonepin, 147);
    } else if (seconds1 == 28 and subseconds1 <4){ //double beep
      tone(tonepin, 147,200);
      delay(200);
      tone(tonepin, 147,200);

    } else if (seconds1 == 30 and subseconds1 <2){ //double beep
      tone(tonepin, 90,200);
    } else  {
      noTone(tonepin);
    }


}

//end stopwatch-routine
void end_stopwatch() {
  stopwatch = false;
  display.clearDisplay();
}



///////////////////
//////FOR PLOTTING

int getIndexOfMaximumValue(float* array, int size){
  int maxIndex = 0;
  int max = array[maxIndex];
  for (int i=1; i<size; i++){
    if (max<array[i]){
      max = array[i];
      maxIndex = i;
    }
  }
  return maxIndex;
}


int map_floattoint(float x, float in_min, float in_max, int out_min, int out_max)
{
  return int((x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min);
}


void  plot_data(){
  display.clearDisplay();
  //plots the storage-array based on storage-size (storage-size should not be longer then screen-width!)
    for (int i = 0; i <= STORAGE_SIZE; i++){
      
      //get maximum value of storage-array
      float maxdata = storage[getIndexOfMaximumValue(storage, STORAGE_SIZE)];

      int x = i;
      //int y = SCREEN_HEIGHT-int(storage[i]); //without adjusting to maximal screen-scale
      int y = map_floattoint(storage[i], 0.0, maxdata, SCREEN_HEIGHT, 0); //map so that it fits to screen

      Serial.print(storage[i]);
      Serial.print(" - ");
      Serial.println(y);

      display.drawPixel( x,  y, WHITE);
    }
    display.display();
}