/*
  0  No Flow fault
  1  Flow fault (leak)
  2  Power Up
  3  Expansion comms fault
  4  Display Ping fault
  5  Wifi Timeout
  6  No AT200 RX Timeout
*/

#define MAXFAULTS 100
int faultCount[MAXFAULTS];
const int faultLimits[MAXFAULTS] = // how many consective faults befor it's real
    {
        1, // 0 powerup
        2, // 1 SD card error
        1, // 2 low battery
        4, // 3
        1, // 4
        1, // 5
        1, // 6
        1,
        1,
        1,
        1, // 10
        1,
        1,
        1,
        1,
        1, // 15
        1,
        1,
        1,
        1,
        1, // 20
        1,
        1,
        1,
        1, // 24
        1, // 25 Obstruction Fault
        1,
        1,
        1,
        1,
        1, // 30
        1,
        1,
        1, // 33 Get motor error
        1, // 34 motor fault
        1, // 35 Lidar obstruction fault
        1, // 36 No display 1
        1,
        1,
        1,
        1, // 40
        1,
        1,
        1,
        1,
        1, // 45
        1,
        1,
        1,
        1, // 49
        1, // 50
        1,
        1,
        1,
        1,
        1, // 55
        1,
        1,
        1,
        1,
        1, // 60
        1,
        1,
        1,
        1,
        1, // 65
        1,
        1,
        1,
        1, // 69
        1, // 70
        1,
        1,
        1,
        1,
        1, // 75
        1,
        1,
        1,
        1,
        1, // 80
        1,
        1,
        1,
        1,
        1, // 85
        1,
        1,
        1,
        1, // 89
        1, // 90
        1,
        1,
        1,
        1,
        1, // 95
        1,
        1,
        1,
        1 // 99
};

#define fault_QSIZ 40
struct faultQ
{
  uint16_t faultnum;
  uint32_t etime;
  int32_t data[6];
} fault_Q[fault_QSIZ], fault_Qtempdata;

int fault_Qhead = 0;
int fault_Qtail = 0;

#define RENLITAOFFSET 400 // Renlita fault num offset in cloud

void initFaults(void)
{
  // int fi;
  // for (fi = 0; fi < MAXFAULTS; fi++) faultCount[fi] = 0;
  memset(faultCount, 0, sizeof(faultCount));
  memset(fault_Q, 0, sizeof(fault_Q));
  fault_Qhead = 0;
  fault_Qtail = 0;
}

void qualifyFault(int fnum, int32_t fdat)
{

  if (fnum < MAXFAULTS)
  {
    if (faultCount[fnum] < faultLimits[fnum])      // no fault last time
      if (++faultCount[fnum] >= faultLimits[fnum]) // no previous fault
      {
        faultQ_push(fnum + RENLITAOFFSET, fdat);
      }
  }
}

void restoreFault(int fnum)
{

  if (fnum < MAXFAULTS)
    if (faultCount[fnum] > 0)
    {
      faultCount[fnum] = 0;
      Serial.print("Fault Restored ");
      Serial.println(fnum);
    }
}

void faultQ_push(int fnum, int32_t fdat) // load tempdata struct first..  pointer sits on next one to add
{

  fault_Q[fault_Qhead].faultnum = fnum;
  fault_Q[fault_Qhead].etime = getEpochRtc();
  fault_Q[fault_Qhead].data[0] = fdat;

  Serial.println("Fault Push");
  Serial.println(fnum);

  if (++fault_Qhead >= fault_QSIZ)
    fault_Qhead = 0; // if at end then wrap

  if (fault_Qhead == fault_Qtail)
    fault_Qtail++; // if hit other pointer then we full
  if (fault_Qtail == fault_QSIZ)
    fault_Qtail = 0; // if at end then wrap
}

void faultQ_pull(void) // dumps into tempdata struct pointer sits on next on to pull
{
  int f;
  fault_Qtempdata.faultnum = fault_Q[fault_Qtail].faultnum;
  fault_Qtempdata.etime = fault_Q[fault_Qtail].etime;

  for (f = 0; f < 6; f++)
    fault_Qtempdata.data[f] = fault_Q[fault_Qtail].data[f];

  Serial.println("Fault Pull");
  Serial.println(fault_Qtempdata.faultnum);

  if (++fault_Qtail == fault_QSIZ)
    fault_Qtail = 0; // if at end then wrap
}

int faultQ_size(void)
{
  if (fault_Qhead >= fault_Qtail)
    return (fault_Qhead - fault_Qtail);
  else
    return ((fault_QSIZ - fault_Qtail) + fault_Qhead);
}
