 int ledArray[] = {12, 9, 5, 2};
 int buttonArray[] = {13, 10, 6, 3};
 int pinCount = 4; 
 int buzzer = 8;
 
 int ledState = 0;
 int gameState = 0;
 
  //Number of lights you have to match to win
 #define NUMBERTOWIN 5
 int gameValues[NUMBERTOWIN];
 int roundNum = 0;

//Pre game lights for me to see what led works or not 
 unsigned long previousMillis = 0;
 unsigned long interval1 = 500; 
 
//Functions 
void setLed(int ledNum);
void displayClue(int roundNum);
boolean waitForInput(int buttonNum);
 
void setup () {
Serial.begin(9600);

Serial.println("setup");
 
  for(int Pin = 0; Pin < pinCount; Pin++)
  {

  pinMode(ledArray[Pin], OUTPUT);
  }
    
  for(int Pin = 0; Pin < pinCount; Pin++)
  {
 
  pinMode(buttonArray[Pin], INPUT_PULLUP);
  }
 
 
 randomSeed(analogRead(0));
 }

void loop () {
  
  if (gameState == 0)
  {
     int button0 = digitalRead(buttonArray[0]);
     int button1 = digitalRead(buttonArray[1]);  
     int button2 = digitalRead(buttonArray[2]); 
     int button3 = digitalRead(buttonArray[3]); 
     
    //if no buttons is pressed the it's the pre game 
    if (button0 && button1 && button2 && button3)
    {
      pre_game();
    }

    //for if the botton is pressed
    else
    {
      Serial.println("button Pressed"); 
    
      setLed(-1);
  
      roundNum = 0;
      delay (1000);
   
      gameState = 1;
    }
  }

  if (gameState == 1)
  {
    gamePlay();
  }
  
  if (gameState == 2)
  {

   //for winning 
    delay(500);
    winning_sound();
    winDisplay();
    winDisplay();
    winDisplay();
    loseDisplay();
    Serial.println("winDisplay");

    delay (1000);

    gameState = 0;
  }
  
  if (gameState == 3)
  {

   //for losing 
    delay(500);
    losing_sound();
    loseDisplay();
    loseDisplay();
    loseDisplay();
    Serial.println("loseDisplay");

    delay (1000);

    gameState = 0;
  } 
}

//the pre game 
void pre_game()
{

  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > interval1)
  {

  if (ledState == 0)
  {
    Serial.println("pre green");
    setLed(0);
    ledState = 1;
  }
  else if (ledState == 1)
  {
    Serial.println("pre red");
    setLed(1);
    ledState = 2;
  }
  else if (ledState == 2)
  {
    Serial.println("pre yellow");
    setLed(2);
    ledState = 3;
  }
  else if (ledState == 3)
  {
    Serial.println("pre blue");
    setLed(3);
    ledState = 0;
  }

  previousMillis = currentMillis;
  }
}


void gamePlay()
{
  Serial.println("gamePlay");

  for ( int i=0; i<NUMBERTOWIN; i++)
  {
    gameValues[i] = floor(random(0,4));
    Serial.println(gameValues[i], DEC);
  }

  
  Serial.print("Starting Round ");
  Serial.println(roundNum, DEC);
  for (int r=0; r<NUMBERTOWIN; r++)
  {
    displayClue(roundNum);
  
    for (int i=0; i<=roundNum; i++)
    {      
      Serial.print("Wainting for input ");
      Serial.print(i+1, DEC);
      Serial.print(" of ");
      Serial.print(roundNum+1, DEC);
      Serial.println("");

         //for the user input waiting 
         if (waitForInput(gameValues[i]))
      {
        if (i==roundNum)
        {
          Serial.println("Correct");
          if (roundNum == NUMBERTOWIN-1)
          {
            Serial.println("Damn you really just beat me ");
    
           gameState = 2;
           return;
          }
          else 
          {
            Serial.println("Continue");
          }
        }
      }
      else 
      {
        Serial.println("HAHAHAHAHA you lost");
        gameState = 3;
        return;
      }
    }
    roundNum++;
    delay(1000);
  }
}

void setLed(int ledNum)
{
  if (ledNum<0)
  {
   for (int i = 0; i<pinCount; i++)
   {
   digitalWrite(ledArray[i], LOW);
   }
  }
  else
  {
    for (int i = 0; i<pinCount; i++)
    {
      if (i == ledNum)
      {
        digitalWrite(ledArray[i], HIGH);
      }
      else 
      {
        digitalWrite(ledArray[i], LOW);
      }
    }
  }
 }


 void displayClue(int roundNum)
 {
  setLed(-1);
  for (int i=0; i<=roundNum; i++)
  {
    setLed(gameValues[i]);
    delay(750);
    setLed(-1);
    delay(250);
  }
 }

boolean waitForInput(int buttonNum)
{
  //read all the buttons continuously until a button is pressed, if a button is pressed check if it's correct and if so return true. if not, return false. 
  while(true) 
  {
   int button0 = digitalRead(buttonArray[0]);
   int button1 = digitalRead(buttonArray[1]);  
   int button2 = digitalRead(buttonArray[2]); 
   int button3 = digitalRead(buttonArray[3]); 
   
   if (!button0 || !button1 || !button2 || !button3)
   {
      delay(250);
      if (buttonNum == 0)
      {
        digitalWrite(ledArray[0], HIGH);
        delay(250);
        digitalWrite(ledArray[0], LOW);
      }
      else if (buttonNum == 1)
      {
        digitalWrite(ledArray[1], HIGH);
        delay(250);
        digitalWrite(ledArray[1], LOW);
      }
      else if (buttonNum == 2)
      {
        digitalWrite(ledArray[2], HIGH);
        delay(250);
        digitalWrite(ledArray[2], LOW);
      }
      else if (buttonNum == 3)
      {
        digitalWrite(ledArray[3], HIGH);
        delay(250);
        digitalWrite(ledArray[3], LOW);
      }
     
      if (buttonNum == 0 && button0 == 0)
      {
        Serial.println("0 Pressed");
        return true;
      }
      else if (buttonNum == 1 && button1 == 0)
      {
        Serial.println("1 Pressed");
        return true;
      }
      else if (buttonNum == 2 && button2 == 0)
      {
        Serial.println("2 Pressed");
        return true;
      }
      else if (buttonNum == 3 && button3 == 0)
      {
        Serial.println("3 Pressed");
        return true;
      }
      else
      {
        return false;
      }
    }
  }
}

//after winning
void winDisplay()
{
digitalWrite(ledArray[0], HIGH);
delay(75);
digitalWrite(ledArray[0], LOW);
delay(75);
digitalWrite(ledArray[1], HIGH);
delay(75);
digitalWrite(ledArray[1], LOW);
delay(75);
digitalWrite(ledArray[2], HIGH);
delay(75);
digitalWrite(ledArray[2], LOW);
delay(75);
digitalWrite(ledArray[3], HIGH);
delay(75);
digitalWrite(ledArray[3], LOW);
delay(75);
digitalWrite(ledArray[2], HIGH);
delay(75);
digitalWrite(ledArray[2], LOW);
delay(75);
digitalWrite(ledArray[1], HIGH);
delay(75);
digitalWrite(ledArray[1], LOW);
delay(75);
digitalWrite(ledArray[0], HIGH);
delay(75);
digitalWrite(ledArray[0], LOW);
delay(75);
}

void winning_sound(void)
{
  Serial.println("buzzer1");
  tone(buzzer, 294, 250);
  delay(200);
  tone(buzzer, 294, 250);
  delay(200);
  tone(buzzer, 294, 250);
  delay(200);
  tone(buzzer, 392, 500);
  delay(500);
  Serial.println("second 392");
  tone(buzzer, 392, 250);
  delay(200);
  tone(buzzer, 440, 250);
  delay(200);
  tone(buzzer, 392, 250);
  delay(200);
  tone(buzzer, 440, 250);
  delay(200);
  tone(buzzer, 494, 500);
}


void loseDisplay()
{
  digitalWrite(ledArray[0], HIGH);
  digitalWrite(ledArray[1], HIGH);
  digitalWrite(ledArray[2], HIGH);
  digitalWrite(ledArray[3], HIGH);
  delay(200);
  digitalWrite(ledArray[0], LOW);
  digitalWrite(ledArray[1], LOW);
  digitalWrite(ledArray[2], LOW);
  digitalWrite(ledArray[3], LOW);
  delay(200);
}

void losing_sound(void)
{
  Serial.println("losing_sound");
  tone(buzzer, 98, 250);
  delay(250);
   tone(buzzer, 93, 250);
  delay(250);
   tone(buzzer, 87, 250);
  delay(250);
}
