//======================================================
// REACTION GAME MAIN ROUTINE
//======================================================

  /* This Game Can Be Called From 
   *  Stand Alone Mode / Bluetooth Connection
   *  The primary mode is the standalone but
   *  if the bluetooth is connected it has the priority
   *  so it will take over the control of the device
   *  
   *  If you want to control the game via bluetooth
   *  you need to call : game_reaction_bluetooth(JSON String)
   *  If you want to use the stand alone mode
   *  you need to call : game_reaction_standalone()
   *  
   *  the game returns a float point number which is
   *  in seconds. so the athlete know how long he takes to react
   */

//======================================================
// Request From Stand Alone Buttons
//======================================================

  void game_reaction_standalone()
  {
    // Variables
    uint8_t   minDelay  = 0;
    uint8_t   maxDelay  = 0;
    uint8_t   trials    = 0;
    
    // Display Screen Menu And Button Actions
    // If The Menu Number 1 -> We Set The Value Of Min Delay
    // If The Menu Number 2 -> We Set The Value Of Max Delay
    // If The Menu Number 3 -> We Set The Number Of Trials

    // Call the Game Play
    play_reaction(minDelay, maxDelay, trials);
  }

//======================================================
//  Request From Bluetooth Via JSON
//======================================================

  /* REACTION GAME SETTINGS PARAMETERS NOTE:
   * ------------------------------------------
   *  
   *  FORMAT :
   *  --------
   *    {"tr": 10, "mn": 1, "mx": 2}
   *  
   *  MEANNING :
   *  ----------
   *    tr : trials pre counter
   *    mn : minimum delay, between trials
   *    mx : maximum delay, between trials
   *  
   *  THINGS THAT ENDS THE GAME :
   *  ---------------------------
   *    1. BY COUNT DOWN "tr" REACH TO ZERO
   *    2. BY A COMMAND "FROM APP VIA BLUETOOTH"
   *  
   *  CALCULATING RESULTS :
   *  ---------------------
   *    Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec
   */

  void game_reaction_bluetooth(String settings)
  {
    //------------------------------------------------------
    // START OF READING THE SETTINGS
    //------------------------------------------------------
    
    // Deserialize the JSON document
    DeserializationError error = deserializeJson(JSON, settings);

    // JSON ERROR
    if(error) {
      dualcomm(JSON_ERROR);
      return;
    }

    // PUBLIC VARIABLES
    uint8_t   minDelay  = JSON["mn"];
    uint8_t   maxDelay  = JSON["mx"];
    uint16_t  trials    = JSON["lm"];

    // Fix Random Error
    maxDelay += 1;
    
    // Clearing Buffer
    JSON.clear();

    // Play The Game
    play_reaction(minDelay, maxDelay, trials);
  }

//======================================================
//  Play The Game
//======================================================

  void play_reaction(uint8_t minDelay, uint8_t maxDelay, uint16_t trials)
  {
    // PUBLIC VARIABLES
    uint16_t  temp      = trials;

    // Fix Random Error
    maxDelay += 1;
    
    // Clearing Buffer
    JSON.clear();

    //------------------------------------------------------
    // PREPARE FOR GAME START
    //------------------------------------------------------
    
    // DisJSON Welcome Message
    terminal("");
    terminal("trials    : " + String(trials) + " Strikes");
    terminal("minDelay  : " + String(minDelay) + " Seconds");
    terminal("maxDelay  : " + String(maxDelay) + " Seconds");
    terminal("2 Seconds To Start Get Ready & Good Luck !!");
    terminal("");

    // Main Variables
    uint16_t      sdelay    = 0;
    uint16_t      power     = 0;
    uint16_t      response  = 0;
    unsigned long startTime = 0;
    unsigned long stopTime  = 0;

    // Ready Signal
    LED_SIGNAL_REACTION_START();

    //-------------------------
    // PREPARE FOR GAME START
    //-------------------------

    // Processing Results
    for(int i=0; i<trials; i++)
    {
      // Reading Kick JSON
      terminal(" ------ Trial Number (" + String(i + 1) + ") ------");
      terminal(" -> Get Ready !!");

      // Set Random Delay Time
      sdelay = random(minDelay, maxDelay);
      sdelay *= 1000;
      delay(sdelay);

      // Light Up Green
      LED_SET_COLOR(0, 255, 0, 255);

      // Start Timer
      startTime = millis();

      // Sensing Strike Power
      while(power < VTH) 
      {
        // Reading The Strike
        power = readImpact();

        // If Stop Command Came From Smart Phone
        if(isBluetooth)
        {
          String msg = Bluetooth.readStringUntil('\n');
          flushBluetooth;
          msg.trim();
          if(msg == CM_STOP) {
            dualcomm(GAME_OVER);
            // LightUp
            LED_SIGNAL_END();
            // RESET
            return;
          }
          else if(msg == CM_RESET) {
            LED_SIGNAL_REACTION_RESET();
            trials = temp;
            break;
          }
        }
      }
  
      // Stop Timer
      stopTime = millis();
  
      // Stop Light
      LED_SET_COLOR(255, 0, 0, 255);
  
      // Calculating Response Time
      response = stopTime - startTime - 1;
  
      // Create Json JSON
      String msg = reaction_JSON_json(i+1, power, response, sdelay);
      
      // Print To Terminal
      dualcomm(msg);
      
      // Clear All
      sdelay    = 0;
      power     = 0;
      response  = 0;
    }

    // Red Light Delay
    delay(500);

    // END GAME
    dualcomm(GAME_OVER);

    // Blink Red
    LED_SIGNAL_CELEBRATION();

    // Return To Game Selector
    return;
  }

//======================================================
// REACTION JSON -> To Send Back To Mobile Device
//======================================================

  String reaction_JSON_json(unsigned int count, unsigned int power, unsigned int response, unsigned int startDelay)
  {
    // Convert To Seconds Unit
    float re = response;
    re /= 1000;

    // Asignning Values
    JSON["ct"]  = count;  // Strike Number
    JSON["pw"]  = power;  // Strike Power In Analog Read
    JSON["sd"]  = startDelay/1000;  // LED Strip Start Delay in Seconds
    JSON["re"]  = String(re, 3).toFloat();  // Strike Reaction Time In Milli Sec
    
    String output;
    serializeJson(JSON, output);
    JSON.clear();
    return output;
  }

//======================================================
// REACTION GAME START LED SIGNAL
//======================================================

  void LED_SIGNAL_REACTION_START()
  {
    // Cross fade the white signal to get ready
    LED_CROSS_FADE(255, 255, 255, 3);
    
    // Set the LED strip color to red
    LED_SET_COLOR(255, 0, 0, 255);
  }
  
//======================================================
// REACTION GAME RESET LED SIGNAL
//======================================================

  void LED_SIGNAL_REACTION_RESET()
  {
    // Light Bright Blue
    LED_BLINK(0, 0, 255, 2);
    
    // Wait For 1/4 Second
    delay(250);
    
    // Fade Out The Blue
    LED_SET_COLOR(0, 255, 0, 255);
  }
