// #include <vector.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

enum buttons {LEFT=2, MID, RIGHT, RESULT};

class Candidate {
  private:
    String name;
    int votes;

  public:
    Candidate(String candidateName) {
      name = candidateName;
      votes = 0;
    }

    void addVote() {
      votes++;
    }

    String getName() {
      return name;
    }

    int getVotes() {
      return votes;
    }
};

Candidate* candidates[20];
int numCandidates = 0;
int currentCandidateIndex = 0;

void(* resetFunc) (void) = 0;

void setup() {
  lcd.init();
  lcd.backlight();
  lcd.print("Election System");
  delay(2000);

  addCandidate("Aarav");
  addCandidate("Sunita");
  addCandidate("Rajendra");
  addCandidate("Anjali");
  addCandidate("Dinesh");
  addCandidate("Kritika");
  addCandidate("Bijay");
  addCandidate("Sweta");
  addCandidate("Niraj");
  addCandidate("Priya");

  displayCurrentCandidate();

  pinMode(LEFT, INPUT);
  pinMode(MID, INPUT);
  pinMode(RIGHT, INPUT);
}

void loop() {

  if (digitalRead(LEFT))
    navigateCandidates(-1);

  if (digitalRead(MID))
    voteCurrentCandidate();

  if (digitalRead(RIGHT))
    navigateCandidates(1);
  
  if (digitalRead(RESULT))
    displayWinner();

}

void addCandidate(String name) {
  if (numCandidates < 20)
  {
    candidates[numCandidates] = new Candidate(name);
    numCandidates++;
  }
}

void navigateCandidates(int direction) {
  currentCandidateIndex += direction;

  if (currentCandidateIndex < 0)
    currentCandidateIndex = numCandidates - 1;

  if (currentCandidateIndex >= numCandidates)
    currentCandidateIndex = 0;

  displayCurrentCandidate();
  delay(300);
}

void voteCurrentCandidate() {
  if (numCandidates > 0) {
    candidates[currentCandidateIndex]->addVote();
    lcd.clear();
    lcd.print("Voted for");
    lcd.setCursor(0, 1);
    lcd.print(candidates[currentCandidateIndex]->getName());
    delay(2000);
    currentCandidateIndex = 0;
    displayCurrentCandidate();
  }
  delay(300);
}

void displayCurrentCandidate() {
  lcd.clear();
  if (numCandidates > 0) {
    lcd.print(candidates[currentCandidateIndex]->getName());
    lcd.setCursor(0, 1);
    lcd.print("Votes: ");
    lcd.print(candidates[currentCandidateIndex]->getVotes());
  }
  else
    lcd.print("No candidates");
}

void displayWinner() {
  if (numCandidates > 0)
  {
    int maxVotes = 0;
    int winnerIndex = 0;

    for (int i = 0; i < numCandidates; i++)
      if (candidates[i]->getVotes() > maxVotes)
      {
        maxVotes = candidates[i]->getVotes();
        winnerIndex = i;
      }
    
    lcd.clear();
    lcd.print("Winner: ");
    lcd.print(candidates[winnerIndex]->getName());
    lcd.setCursor(0, 1);
    lcd.print("Votes: ");
    lcd.print(maxVotes);
    delay(5000);

    lcd.clear();
    lcd.print("Resetting.");
    for (int i = 0; i <= 5; i++)
    {
      if (i == 3) lcd.noBacklight();
      delay(1000);
      lcd.print('.');
    }
    resetFunc();
  }
}

/*
void displayWinner() {
  if (numCandidates > 0)
  {
    int maxVotes = 0;
    std::vector<int> winnerIndices;

    for (int i = 0; i < numCandidates; i++) {
      int candidateVotes = candidates[i]->getVotes();
      if (candidateVotes > maxVotes)
      {
        maxVotes = candidateVotes;
        winnerIndices.clear();
        winnerIndices.push_back(i);
      }
      else if (candidateVotes == maxVotes)
        winnerIndices.push_back(i); // Add the index of this candidate
    }
    
    lcd.clear();
    lcd.print("Winners:");
    delay(2000);

    for (int i = 0; i < winnerIndices.size(); i++)
    {
      int winnerIndex = winnerIndices[i];
      lcd.clear();
      lcd.print("Winner: ");
      lcd.print(candidates[winnerIndex]->getName());
      lcd.setCursor(0, 1);
      lcd.print("Votes: ");
      lcd.print(maxVotes);
      delay(5000);
    }

    lcd.clear();
    lcd.print("Resetting.");
    for (int i = 0; i <= 5; i++)
    {
      if (i == 3) lcd.noBacklight();
      delay(1000);
      lcd.print('.');
    }
    resetFunc();
  }
}
*/
$abcdeabcde151015202530fghijfghij