#ifndef _HELPFUNCTIONS_H_
#define _HELPFUNCTIONS_H_

#include <Arduino.h>
#include <ArduinoSort.h>

float getMean(uint16_t *parray,uint16_t psize);
float getMeanf(float *parray,uint16_t psize);
uint16_t getMin(uint16_t *parray, uint16_t psize);
uint16_t getMax(uint16_t *parray, uint16_t psize);
float getMaxf(float *parray,uint16_t psize);
float getMinf(float *parray, uint16_t psize);
bool isValueArrayOK(uint16_t *parray,uint16_t psize, uint16_t pcheck);
bool isValueArrayOKf(float *parray,uint16_t psize, float pcheck);
float getFilteredf(float *parray,uint16_t psize, uint16_t pcutOff);
float mapf(float x, float in_min, float in_max, float out_min, float out_max);


float getMean(uint16_t *parray,uint16_t psize) {
  double mean=0;
  for (uint16_t i=0;i<psize;i++) {
    mean+=parray[i];
  }

  return mean/psize;
}
float getMeanf(float *parray,uint16_t psize) {
  double mean=0;
  for (uint16_t i=0;i<psize;i++) {
    mean+=parray[i];
  }

  return mean/psize;
}

bool isValueArrayOK(uint16_t *parray,uint16_t psize, uint16_t pcheck) { //check if array has error values
  for (uint16_t i=0;i<psize;i++) {
    if (parray[i]==pcheck){
      return false;
    }
  }
  return true;
}
bool isValueArrayOKf(float *parray,uint16_t psize, float pcheck) { //check if array has error values
  for (uint16_t i=0;i<psize;i++) {
    if (parray[i]==pcheck){
      return false;
    }
  }
  return true;
}




uint16_t getMin(uint16_t *parray, uint16_t psize) {
  uint16_t min=65535;
  for (uint16_t i=0;i<psize;i++) {
    if (parray[i]<min) {
      min=parray[i];
    }
  }

  return min;
}

uint16_t getMax(uint16_t *parray,uint16_t psize) {
  uint16_t max=0;
  for (uint16_t i=0;i<psize;i++) {
    if (parray[i]>max) {
      max=parray[i];
    }
  }

  return max;
}

float getMinf(float *parray, uint16_t psize) {
  float min=65535;
  for (uint16_t i=0;i<psize;i++) {
    if (parray[i]<min) {
      min=parray[i];
    }
  }

  return min;
}

float getMaxf(float *parray,uint16_t psize) {
  float max=0;
  for (uint16_t i=0;i<psize;i++) {
    if (parray[i]>max) {
      max=parray[i];
    }
  }

  return max;
}


float getFilteredf(float *parray,uint16_t psize, uint16_t pcutOff) {
  //cuts off lowest and highest pcutOff values from array, then returns the mean of the psize-2*pcutOff center values.
  //pcutOff < psize/2

  float _copy[psize];
  std::copy(parray,parray + psize, _copy);
  sortArray(_copy,psize);

  double mean=0;
  for (uint16_t i=pcutOff;i<psize-pcutOff;i++) {
    mean+=_copy[i];
  }

  return mean/(psize-2*pcutOff);
}

float mapf(float x, float in_min, float in_max, float out_min, float out_max)
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}



void i2cscan()
{
  byte error, address;
  int nDevices;
 
  delay(500);
  Serial.println("Scanning...");
 
  nDevices = 0;
  for(address = 1; address < 127; address++ )
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
 
    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");
 
      nDevices++;
    }
    else if (error==4)
    {
      Serial.print("Unknown error at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.println(address,HEX);
    }    
  }
}


#endif 