// Project 17 - Making a Binary Quiz Game
#include <SPI.h>
#include <Streaming.h>
Print &cout {Serial};

//
// Global constant(s)
//
namespace gc {
 //SPI Pin 11 -> DS (Data) ; Pin 13 -> SHCP (Latch)
constexpr uint8_t csPin {10};         // SPI CS PIN (STCP) Clock
}    

//
// Display a bit string with leading zeros on serial console
//
template <typename T> void printBits(Stream &st, const T &value) {
  constexpr uint8_t maxBits = (sizeof(T) * 8);
  constexpr T mask = (static_cast<T>(0x01) << (maxBits - 1));

  uint8_t i = 0;
  while (i < maxBits) {
    st << (((value << i++) & mask) ? 1 : 0);
    // Output a space after each nibble.
    if (!(i - ((i >> 2) << 2))) { st << " "; }
  }
}

//
// Show the bit pattern (LEDs) by shifting the value to the 74HC595
// 
void displayNumber(uint8_t value)
{
  digitalWrite(gc::csPin, LOW);
  SPI.transfer(value);
  digitalWrite(gc::csPin, HIGH);
}

//
// receive the answer from the player
//
uint8_t getAnswer()
{
  char character {0};
  uint8_t answer {0};

  Serial.flush();
  while (Serial.available() == 0) {}   // do nothing until something comes into the serial buffer
  while (Serial.available() > 0)       // one character of serial data is available, begin calculating
  {
    character = Serial.read();
    if (character == '\n') {
      break;
    } else {
      answer *= 10;
      character -= '0';
      answer += character;
    }
    delay(5);   // allow a short delay for any more numbers to come into Serial.available
  }
  cout << "You entered: " << answer << endl;
  return answer;
}

//
// check the answer from the player and show the results
//
void checkAnswer(uint8_t answer, uint8_t number) {
  (answer == number) ? cout << "Correct :-)" : cout << "Incorrect :-(";
  cout << " -> ";
  printBits(Serial, number);
  cout << "equals " << number << endl << endl;
  delay(10000); // give the player time to review his or her answers
}

void setup()
{
  pinMode(gc::csPin, OUTPUT);
  SPI.begin();
  Serial.begin(115200);
  randomSeed(analogRead(0));    // initialize the random number generator
  displayNumber(0);             // clear the LEDs
}

void loop()
{
  uint8_t num = random(256);
  displayNumber(num);
  cout << "What is the binary number in base-10? " << endl;
  checkAnswer(getAnswer(), num);
}
74HC595