#include "Display.h"

// Constructor implementation
EPaper Display::_epaper;
Display::Display() {}
void Display::init(){
    _epaper.begin();
    _epaper.fillScreen(TFT_WHITE);
    _epaper.setTextColor(TFT_BLACK, TFT_WHITE); // Adding a background colour erases previous text automatically
    
    _drawScreenLayout();
    refreshDisplay();
}
void Display::refreshDisplay(){
  _epaper.update();
  //_epaper.sleep();
}
void Display::_drawScreenLayout(){
  _drawFPS();
  _drawFPE();
  showChronographDisconnected();
  _drawShotCount();
  _drawAverageFPS();
  _drawLowFPS();
  _drawHighFPS();
  _drawSpread();
  _drawStandardDeviation();
  _drawProfile();
  _drawLastShots();
}
void Display::_drawFPE(){
  _epaper.setTextSize(2);
  _epaper.drawString("FPE: ",20,240);
}
void Display::updateFPE(int fpe){
  _epaper.fillRect(65,230,100,35,TFT_WHITE);
  char buffer[10];
  itoa(fpe, buffer, 10);
  _epaper.setTextSize(2);
  _epaper.drawString(buffer,70,240);
}
void Display::_drawFPS(){
  _epaper.drawRoundRect(10, 10, 300, 260, 10, TFT_BLACK);
  _epaper.setTextSize(2);
  _epaper.drawString("Latest Shot:", 15, 15);
}
void Display::updateFPS(int fps){    
    if (fps>0){
        _epaper.fillRoundRect(20, 70, 280, 110, 15, TFT_WHITE);
        _epaper.setTextSize(20);
        char floatCharArray[10];
        dtostrf(fps, 3, 0, floatCharArray);
        _epaper.drawString(floatCharArray, 100, 100);
        _epaper.setTextSize(2);
        _epaper.drawString("fps", 145, 155);
    }
    else{
        _epaper.fillRoundRect(20, 70, 280, 110, 15, TFT_WHITE);
        _epaper.setTextSize(20);
        _epaper.drawString(" -", 100, 100);
        _epaper.setTextSize(2);
        _epaper.drawString("fps", 145, 155);
    }
}
void Display::_drawAverageFPS(){
  _epaper.drawRoundRect(450, 10, 120, 80, 10, TFT_BLACK);
  _epaper.setTextSize(2);
  _epaper.drawString("Avg FPS:",465,15);
  _epaper.setTextSize(4);
  _epaper.drawString("-",475,45);
}
void Display::updateAverageFPS(int fps){
  _epaper.fillRoundRect(460, 35, 100, 45, 10, TFT_WHITE);
  _epaper.setTextSize(4);
  if (fps>0){
    char buffer[10];
    itoa(fps, buffer, 10);
    _epaper.drawString(buffer,475,45);
  }
  else{
    _epaper.drawString("-",475,45);
  }
}
void Display::_drawLowFPS(){
  _epaper.drawRoundRect(450, 100, 120, 80, 10, TFT_BLACK);
  _epaper.setTextSize(2);
  _epaper.drawString("Low FPS:",465,105);
  _epaper.setTextSize(4);
  _epaper.drawString("-",475,135);
}
void Display::updateLowFPS(int fps){
  _epaper.fillRoundRect(460, 125, 100, 45, 10, TFT_WHITE);
    _epaper.setTextSize(4);
    if (fps>0){
        char buffer[10];
        itoa(fps, buffer, 10);
        _epaper.drawString(buffer,475,135);
    }
    else{
        _epaper.drawString("-",475,135);
    }
}
void Display::_drawHighFPS(){
  _epaper.drawRoundRect(450, 190, 120, 80, 10, TFT_BLACK);
  _epaper.setTextSize(2);
  _epaper.drawString("High FPS:",460,195);
  _epaper.setTextSize(4);
  _epaper.drawString("-",475,225);
}
void Display::updateHighFPS(int fps){
  _epaper.fillRoundRect(460, 215, 100, 45, 10, TFT_WHITE);
  _epaper.setTextSize(2);
  _epaper.drawString("High FPS:",460,195);
  _epaper.setTextSize(4);
  if (fps>0){
    char buffer[10];
    itoa(fps, buffer, 10);
    _epaper.drawString(buffer,475,225);
  }
  else{
    _epaper.drawString("-",475,225);
  }
}
void Display::_drawProfile(){
  _epaper.drawRoundRect(580, 40, 210, 230, 10, TFT_BLACK);
  _epaper.setTextSize(2);
  _epaper.drawString("Profile:", 585, 45);
}
void Display::updateProfile(ChronoProfile& profile){
  String gunName=profile.getGunProfile().getName();
  int powerLevel=profile.getGunProfile().getPowerLevel() + 1;
  _epaper.fillRect(590, 70, 280, 120, TFT_WHITE);
  _epaper.drawRoundRect(580, 40, 210, 230, 10, TFT_BLACK);
  _epaper.setTextSize(2);
  _epaper.drawString(gunName, 595, 75);
  _epaper.drawCircle(770, 56, 12, TFT_BLACK);
  char buffer[10];
  itoa(powerLevel, buffer, 10);
  _epaper.drawString(buffer, 766, 49);

  String projectileName=profile.getProjectileProfile().getName();
  String projectileType=profile.getProjectileProfile().getType();
  float projectileWeight=profile.getProjectileProfile().getWeight();
  float projectileCaliber=profile.getProjectileProfile().getCaliber();
  _epaper.drawString(projectileName, 595, 105);
  char buffer3[10];
  dtostrf(projectileCaliber, 0, 2, buffer3);
  char buffer4[10];
  strncpy(buffer4, buffer3 + 1, 4);
  _epaper.drawString(buffer4, 595, 130);
  _epaper.drawString(projectileType, 595, 155);
  char buffer2[10];
  dtostrf(projectileWeight, 1, 2, buffer2);
  char out[20];
  strcpy(out,buffer2);
  strcat(out,"g");
  _epaper.drawString(out, 595, 180);
}
void Display::_drawShotCount(){
  _epaper.drawRoundRect(320, 10, 120, 80, 10, TFT_BLACK);
  _epaper.setTextSize(2);
  _epaper.drawString("Count:",325,15);
  _epaper.setTextSize(4);
  _epaper.drawString("-",335,45);
}
void Display::updateShotCount(int count){
  _epaper.fillRoundRect(330, 35, 100, 45, 10, TFT_WHITE);
  char buffer[10];
  itoa(count, buffer, 10);
  _epaper.setTextSize(4);
  _epaper.drawString(buffer,335,45);
}
void Display::_drawSpread(){
  _epaper.drawRoundRect(320, 100, 120, 80, 10, TFT_BLACK);
  _epaper.setTextSize(2);
  _epaper.drawString("Spread:",325,105);
  _epaper.setTextSize(4);
  _epaper.drawString("-",335,135);
}
void Display::updateSpread(int spread){
  _epaper.fillRoundRect(330, 125, 100, 45, 10, TFT_WHITE);
  _epaper.setTextSize(2);
  _epaper.drawString("Spread:",325,105);
  _epaper.setTextSize(4);
  if (spread>=0){
    char buffer[10];
    itoa(spread, buffer, 10);
    _epaper.drawString(buffer,335,135);
  }
  else{
    _epaper.drawString("-",335,135);
  }
}
void Display::_drawStandardDeviation(){
  _epaper.drawRoundRect(320, 190, 120, 80, 10, TFT_BLACK);
  _epaper.setTextSize(2);
  _epaper.drawString("SD:",325,195);
  _epaper.setTextSize(4);
  _epaper.drawString("-",335,225);
}
void Display::updateStandardDeviation(float sd){
  _epaper.fillRoundRect(330, 215, 100, 45, 10, TFT_WHITE);
  if (sd==0){
    _epaper.setTextSize(4);
    _epaper.drawString("-",335,225);
  }
  else{
    _epaper.setTextSize(3);
    char buffer[10];
    dtostrf(sd, 1, 2, buffer);
    _epaper.drawString(buffer,335,225);
  }
}
void Display::_drawLastShots(){
  _epaper.drawRoundRect(10, 280, 780, 190, 10, TFT_BLACK);
  _epaper.setTextSize(2);
  _epaper.drawString("Last Shots:",15,285);
}
void Display::updateLastShots(LinkedList<ChronoReading> &chronoReadings){
  _epaper.fillRoundRect(20, 305, 760, 155, 10, TFT_WHITE);
    const int max=32;
    _epaper.setTextSize(2);
    int chronographReadingCount=chronoReadings.size();
    if (chronographReadingCount>0){
        int x=25;
        int y=310;
        for (int i=0;i<chronographReadingCount;i++){
            if (i>=max){break;}
            int c=chronographReadingCount-i;
            int fps=chronoReadings.get(chronographReadingCount-i-1).getFPS();
            int fpe=chronoReadings.get(chronographReadingCount-i-1).getFPE();
            char charArray[50];
            sprintf(charArray, "%d) %d / %d", c, fps, fpe);
            if (i%8 == 0 && i>0){x=x+190; y=310;}
            _epaper.drawString(charArray, x, y);
            y=y+20;
        }
    }
}
void Display::showChronographConnected(){
  _epaper.fillRoundRect(20, 70, 280, 110, 15, TFT_WHITE);
  //_epaper.update();
  _epaper.setTextSize(20);
  _epaper.drawString(" -", 100, 100);
  _epaper.setTextSize(2);
  _epaper.drawString("fps", 145, 155);
}
void Display::showChronographDisconnected(){
  _epaper.setTextSize(3);
  _epaper.fillRoundRect(20, 70, 280, 110, 15, TFT_BLACK);
  //_epaper.update();
  _epaper.setTextColor(TFT_WHITE, TFT_BLACK);
  _epaper.drawString("Searching", 80, 80);
  _epaper.drawString("for", 135, 110);
  _epaper.drawString("chronograph...", 35, 140);
  _epaper.setTextColor(TFT_BLACK, TFT_WHITE);
}
void Display::updateTime(String time){
  _epaper.drawRect(698, 8, 102, 35, TFT_WHITE);   //reset to get rid of ghosting
  _epaper.update();
  _epaper.setTextSize(3);
  _epaper.drawString(time,700,10);
}
void Display::updateEntireDisplay(){
  ChronoReadingManager& chronoReadings = ChronoReadingManager::getInstance();

  //update display
  updateFPS(chronoReadings.getLastFPS());
  updateFPE(chronoReadings.getLastFPE());
  updateShotCount(chronoReadings.getShotCount());
  updateAverageFPS(chronoReadings.getAvgFPS());
  updateLowFPS(chronoReadings.getLowFPS());
  updateHighFPS(chronoReadings.getHighFPS());
  updateSpread(chronoReadings.getSpread());
  updateStandardDeviation(chronoReadings.getStandardDeviation());
  LinkedList<ChronoReading> &readings=chronoReadings.getChronographReadings();
  updateLastShots(readings);
}