#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 10, 9, 8, 7);

// Caracteres customizados para a bateria
byte batteryEmpty[8] = {
  B01111, B11000, B10101, B10100, B10100, B10100, B11000, B01111
};
byte batteryOutline[8] = {
  B11111, B00000, B11001, B00000, B00000, B00000, B00000, B11111
};
byte batteryPartial[8] = {
  B11100, B00100, B10111, B00101, B00111, B00111, B00100, B11100
};
byte batteryAlmostFull[8] = {
  B1111, B11111, B10110, B10111, B10111, B10111, B11111, B1111
};
byte batteryFull[8] = {
  B11100, B11100, B01111, B11101, B11111, B11111, B11100, B11100
};
byte batteryThreeQuarter[8] = {
  B11111, B11111, B00110, B11111, B11111, B11111, B11111, B11111
};
byte batteryOneThird[8] = {
  B11111, B11000, B00001, B11000, B11000, B11000, B11000, B11111
};
byte batteryTwoThird[8] = {
  B11111, B11110, B00111, B11110, B11110, B11110, B11110, B11111
};

// Caracteres customizados para a régua de nível
byte levelEmpty[8] = {
  B00000, B00000, B00000, B00000, B00000, B00000, B00000, B11111
};
byte levelQuarter[8] = {
  B00000, B00000, B00000, B00000, B00000, B11111, B11111, B11111
};
byte levelHalf[8] = {
  B00000, B00000, B00000, B11111, B11111, B11111, B11111, B11111
};
byte levelThreeQuarter[8] = {
  B00000, B11111, B11111, B11111, B11111, B11111, B11111, B11111
};
byte levelFull[8] = {
  B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111
};

// Definição de estados de exibição da bateria
char batteryStates[10][4] = {
  {0, 1, 1, 2}, {3, 1, 1, 2}, {3, 6, 1, 2},
  {3, 7, 1, 2}, {3, 5, 1, 2}, {3, 5, 6, 2},
  {3, 5, 7, 2}, {3, 5, 5, 2}, {3, 5, 5, 4}
};

void setup() {
  lcd.begin(16, 2);
  lcd.createChar(0, batteryEmpty);
  lcd.createChar(1, batteryOutline);
  lcd.createChar(2, batteryPartial);
  lcd.createChar(3, batteryAlmostFull);
  lcd.createChar(4, batteryFull);
  lcd.createChar(5, batteryThreeQuarter);
  lcd.createChar(6, batteryOneThird);
  lcd.createChar(7, batteryTwoThird);
  
  lcd.setCursor(0, 1);
  lcd.print("Preparando...");
  delay(1000);
  lcd.clear();

  // Demonstra os estados da bateria e da régua no início
  initializeDisplays();
}

void loop() {
  updateDisplays();
  delay(500); // Atualização a cada meio segundo
}

void initializeDisplays() {
  for (int i = 0; i <= 8; i++) {
    lcdBatteryStatus(i, 0);
    lcdBatteryLevel(i * 12.5); // Calcula o percentual aproximado
    delay(500);
  }
}

void updateDisplays() {
  int batteryLevel = analogRead(A0);
  int batteryState = map(batteryLevel, 0, 1023, 0, 8);

  lcdBatteryStatus(batteryState, 0);
  lcdBatteryLevel(batteryState * 12.5);

  int rulerLevel = analogRead(A1);
  int rulerState = map(rulerLevel, 0, 1023, 0, 100);

  lcdRulerLevel(rulerState);
}

void lcdBatteryStatus(int state, int row) {
  lcd.setCursor(0, row);
  for (int i = 0; i < 4; i++) {
    lcd.write(batteryStates[state][i]);
  }
}

void lcdBatteryLevel(int percent) {
  lcd.setCursor(0, 1);
  lcd.print("Bat:");
  lcd.print(percent);
  lcd.print("%  ");
}

void lcdRulerLevel(int percent) {
  lcd.setCursor(10, 1);
  lcd.print("L:");
  lcd.print(percent);
  lcd.print("% ");
}