//======================================================
// TIME ATTACK 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 : time_attack_bluetooth(JSON String)
   *  If you want to use the stand alone mode
   *  you need to call : time_attack_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 time_attack_standalone()
  {
    // Variables
    uint16_t time     = 0; 
    uint16_t timer    = 0; 
    uint16_t limit    = 0; 
    bool limitEnable  = 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
    game_timeAttack(time, timer, limit, limitEnable);
  }

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

  /* TIME ATTACK GAME SETTINGS PARAMETERS NOTE:
   * ------------------------------------------
   *  
   *  FORMAT :
   *  --------
   *    {"tm": 10, "le": false, "lm": 10}
   *
   *    tm : count down timer starting value
   *    le : stands for limit enable, if is TRUE the game end if target value is meet
   *    lm : targeted amount of kicks
   *  
   *  THINGS THAT ENDS THE GAME :
   *  ---------------------------
   *    1. BY COUNT DOWN "tm" REACH TO ZERO
   *    2. BY A COMMAND "FROM APP VIA BLUETOOTH"
   *    3. BY LIMITS MEET "WHEN NUMBER OF YOUR KICKS REACH TO lm VALUE"
   *  
   *  CALCULATING RESULTS :
   *  ---------------------
   *    Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec
   *    Delay Between Kicks = Time Of Current Kick - Time Of Last Kick
   *  
   *  RETURNNING JSON FORMAT :
   *  ------------------------
   *    {"tm" : 82, "ct" : 10, "dl" : 1234, "st" : 585}
   *    
   *    tm  : timer count in Sec
   *    ct  : strike counter (number of kicks)
   *    dl  : delay between strikes
   *    st  : time stampe of the strike in milli Seconds
   */

  void time_attack_bluetooth(String settings)
  {   
    // Deserialize the JSON document
    DeserializationError error = deserializeJson(JSON, settings); // the main JSON body container

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

    // PUBLIC VARIABLES
    uint16_t  time        = JSON["tm"]; // Time Window To JSON
    uint16_t  timer       = time;
    uint16_t  limit       = JSON["lm"]; // Kick Target Limit
    bool      limitEnable = JSON["le"]; // Enable Kick Target Limit

    // Clearing Buffer
    JSON.clear();

    // Play The Game
    game_timeAttack(time, timer, limit, limitEnable);
  }

//======================================================
//  Play Time Atack Game
//======================================================

  void game_timeAttack(uint16_t time, uint16_t timer, uint16_t limit, bool limitEnable) 
  {
    // Building Timers 1000mSec -> 1Sec
    TimeTrigger   sec_tick(1000);

    // Kick Counter
    uint16_t counter = 0;

    // Start LED Signal
    LED_SIGNAL_START();

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

    // Send Initial DisJSON
    dualcomm(timeAttack_JSON_json(timer, counter, 0, 0));

    // staring Of time stamp
    unsigned long startStamp = millis();
    
    // store the time of the previous kick
    unsigned long lastStamp = 0;

    // reseting time ticker
    sec_tick.Reset();

    // While The Game Is Still On
    while(timer != 0)
    {
      // Time Stamp
      unsigned long timeStamp = millis() - startStamp;

      // If Stop Command Came From Smart Phone
      if(isBluetooth)
      {
        String msg = Bluetooth.readStringUntil('\n');
        flushBluetooth;
        msg.trim();
        if(msg == CM_STOP) 
        {
          dualcomm(GAME_OVER);
          // Grean Light In
          LED_SIGNAL_END();
          // Return
          return;
        }
        else if(msg == CM_RESET)
        {
          timer = time;
          counter = 0;
          startStamp = millis();
          timeStamp = startStamp;
          lastStamp = timeStamp;
          sec_tick.Reset();
          dualcomm(timeAttack_JSON_json(timer, counter, lastStamp, timeStamp));
          LED_SIGNAL_RESET();
        }
      }
      
      // Every Kick ---------------------------->>>
      if(readImpact() > VTH)
      {
        counter++;
        dualcomm(timeAttack_JSON_json(timer, counter, lastStamp, timeStamp));
        lastStamp = timeStamp;
        delay(100);
      }

      // Every Second ---------------------------->>>
      if(sec_tick.Trigger())
      {
        timer--;
        dualcomm(timeAttack_JSON_json(timer, counter, 0, 0));
      }
      
      // If Limits Are Enabled And Meet
      if(limitEnable == true && counter == limit)
      {
        // END GAME
        dualcomm(GAME_OVER);
        // Celebrate
        LED_SIGNAL_CELEBRATION();
        // Return
        return;
      }
    }

    // Send End Game Signal To Smart Phone
    dualcomm(GAME_OVER);
    // LightUp
    LED_FADEIN(255, 0, 0);   // RED Color
    delay(2000);        // Delay 2000
    LED_CLEAR();        // CLEAR OFF
    // Return
    return;
  }

//======================================================
// TIME ATTACK KICK JSON -> To Send Back To Mobile
//======================================================

  String timeAttack_JSON_json(unsigned int RunningTime, unsigned int KickCount, unsigned int LastStamp, unsigned int TimeStamp)
  {  
    // Building The Buffer
    JSON["tm"]  = RunningTime;
    JSON["ct"]  = KickCount;

    // Calculations
    if(TimeStamp > 0) 
    {
      // Calculate Time Stamp In Seconds
      float st = TimeStamp;
      st /= 1000;
      JSON["st"] = String(st, 3).toFloat();
      
      // Calculate Strike Delay In Seconds
      float dl = TimeStamp - LastStamp;
      dl /= 1000;
      JSON["dl"] = String(dl, 3).toFloat();
    }
    
    String output;
    serializeJson(JSON, output);
    JSON.clear();
    return output;
  }
