#include <SD.h>
#include "ArchivoSD.h"

const char * colNames[] = {"Milis", "TempExt", "Hum", "TempInt", "Alt", "Pres", "AcelX", "AcelY", "AcelZ", "MagX", "MagY", "MagZ", "gpsVal", "nSatelites", "PDOP", "HDOP", "VDOP" , "Fecha", "lat", "lon", "Alt(GPS)", "Direccion", "Velocidad"  };
//--------------------------------------------------------------------------------------
ArchivoSD::ArchivoSD(int pinCS)
{
  pin_sd_cs = pinCS;
}

bool ArchivoSD::init_()
{
  falloSD = false;
  nLines = NLINEMAX;
  nFiles = 0;
  iCol = 0;

  if (SD.begin(pin_sd_cs))
  {
    createColNames();
    //updatefileName();
  }
  else
  {
    falloSD = true;
  }
  return !falloSD;
}

/*
   Actualiza el nombre del archivo en funcion de cuantos archivos lleve, empieza en datalog0000.txt
   y acaba en datalog9999.txt
   Si se necesitan mas archivos, aumentar el 4 cifras a mas
*/
void ArchivoSD::updatefileName()
{
  sprintf(fileName, "%s.csv", Timestamp);
  //strcpy(fileName, "data.csv");
  Utiles::printCOM(fileName);
  nLines = -1;
  //escribe las cabeceras del archivo
  writeColNames();
}

/*
   Escribe en el fichero los nombres a las cabeceras de las columnas
*/
void ArchivoSD::createColNames()
{
  //hace la cadena de nombre
  buffHeaders[0] = 0;
  //copia el primero
  strcpy(buffHeaders, colNames[0]);
  //copia los demas
  for (int i = 1; i < NCOLS; i++)
  {
    sprintf(buffHeaders, "%s;%s", buffHeaders, colNames[i]);
  }
  Utiles::printCOM(buffHeaders);
}

void ArchivoSD::writeColNames()
{
  //abre el archivo y escribe la fila con los nombres de cabecera
  Utiles::printCOM("Crea archivo");
  openFile();
  writeLine(buffHeaders);
  closeFile();
  compruebaFile();

}

bool ArchivoSD::compruebaFile()
{
  delay(50);
  if (! SD.exists(fileName))
  {
    Utiles::printCOM2("Error al comprobar archivo:  ");
    Utiles::printCOM(fileName);
    return false;
  }
  return true;
}

void ArchivoSD::openFile()
{
  if (falloSD)
  {
    if (!init_())
      return;
  }

  //comprueba si ha llegado al maximo de lineas
  if (nLines >= NLINEMAX)
  {
    nFiles++;
    //atualiza el nombre del archivo con 1 mas para la  proxima vez que lo abra
    updatefileName();
    ;
  }
  if (falloSD)
    return;
  file = SD.open(fileName, FILE_WRITE);
  delay(50);
  //incrementa el numero de limeas
  nLines++;
  iCol = 0;
  if (!file)
  {
    Utiles::printCOM("Error al abrir archivo: ");
    Utiles::printCOM(fileName);
    falloSD = true;
  }


}

void ArchivoSD::closeFile()
{
  if (falloSD)
    return;

  file.close();
  /*
    //comprueba si ha llegado al maximo de lineas
    if (nLines >= NLINEMAX)
    {
    nFiles++;
    //atualiza el nombre del archivo con 1 mas para la  proxima vez que lo abra
    updatefileName();
    ;
    }*/
}

/*
   Para escribir al archivo una columna con un valor decimal
   devuelve el buffer por si se quiere usar fuera
*/
void ArchivoSD::writeVal(float val_)
{

  dtostrf(val_, NUM_INT, NUM_DEC, buff);
  printColCOM();
  if (falloSD)
  {
    iCol++;
    return;
  }

  file.print(buff);
  endCol();
}
/*
   Para escribir al archivo una columna con un valor decimal
   devuelve el buffer por si se quiere usar fuera
*/
void ArchivoSD::writeValPrec(float val_)
{

  dtostrf(val_, NUM_INT, NUM_DEC_PREC, buff);
  printColCOM();
  if (falloSD)
  {
    iCol++;
    return;
  }

  file.print(buff);
  endCol();
}
/*
   Para escribir al archivo una columna con un valor entero
   devuelve el buffer por si se quiere usar fuera
*/
void ArchivoSD::writeVal(long unsigned int val_)
{

  sprintf(buff, "%lu", val_);

  printColCOM();
  if (falloSD)
  {
    iCol++;
    return;
  }

  file.print(val_);

  endCol();
}

/*
   Para escribir al archivo una columna con un valor de texto
   devuelve el buffer por si se quiere usar fuera
*/
void ArchivoSD::writeVal(char *val_)
{


  strcpy(buff, val_);

  printColCOM();
  if (falloSD)
  {
    iCol++;
    return;
  }
  file.print(val_);
  endCol();
}

/*
   Despues de cada dato, escribe un ; o bien un caracter vacio si es el ultimo
*/
void ArchivoSD::endCol()
{
  iCol++;

  //si va a haber mas columnas, pone un ;
  //si no, un caracter vacio y salto de linea (ln)
  if (iCol < NCOLS)
  {
    file.print(";");
  }
  else
  {
    file.println("");
  }
}

/*
   Escribe al archivo una linea entera
*/
void ArchivoSD::writeLine(char *line)
{
  if (falloSD)
    return;

  file.println(line);
}


/*
   Imprime el buff por el puerto com
*/
void ArchivoSD::printColCOM()
{
  
  Utiles::printCOM2(colNames[iCol % NCOLS]);
  Utiles::printCOM2(": ");
  Utiles::printCOM2(buff);

}

//------------------------------------------------------------------------------------------------------------------------------------
ArchivoConfig::ArchivoConfig()
{
  n = -1;
}
char* ArchivoConfig::GetTlfInfo(int i)
{
  if (n < 0 || n < i)
    return NULL;
  if (tlf[i].infoSMS)
    return tlf[i].tlf;
  return NULL;
}
char* ArchivoConfig::GetTlfData(int i)
{
  if (n < 0 || n < i)
    return NULL;
  if (tlf[i].dataSMS)
    return tlf[i].tlf;
  return NULL;
}
int ArchivoConfig::GetLen()
{
  return n + 1;
}
bool ArchivoConfig::ini()
{

  char buf[128];
  apn[0] = 0;
  srv[0] = 0;
  TimerSD= TIMER_SD;
  TimerGPRS= TIMER_GPRS;
  TimerSMSData = TIMER_SMS_DATA;
  TimerSMSInfo= TIMER_SMS_INFO;

  file = SD.open("config.txt", FILE_READ);
  if (!file)
    return false;
  n = -1;
  Utiles::printCOM("lee configuracion");
  while (leeLinea(buf)[0] && n < NUM_MAX_TLF) {
    if (buf[0] == '#')
      continue;
    if (strstr(buf, "APN"))
        leeAPN(buf);
    else if (strstr(buf, "SRV"))
        leeSRV(buf);
    else if (strstr(buf, "TIMER_SMS_INFO"))
        leeTSMSI(buf);
    else if (strstr(buf, "TIMER_GPRS"))
        leeTGPRS(buf);
    else if (strstr(buf, "TIMER_SMS_APPDATA"))
        leeTSMSD(buf);
    else if (strstr(buf, "TIMER_SD"))
        leeTSD(buf);
    else
        leetlf(buf);
  }
  file.close();
  return true;
}
char* ArchivoConfig::GetAPN()
{
    return apn;
}
char* ArchivoConfig::GetSRV()
{
    return srv;
}
void ArchivoConfig::leeSRV(char* buf)
{
    StringSplit sp(buf, "=");
    sp.get();
    char* dato = sp.get();
    if (strlen(dato) <= 0)
    {
        Utiles::printCOM("srv mal");
        return;
    }
    strcpy(srv, dato);
    Utiles::printCOM2("srv leida: ");
    Utiles::printCOM(apn);
}
void ArchivoConfig::leeAPN(char* buf)
{
    StringSplit sp(buf, "=");
    sp.get();
    char* dato = sp.get();
    if (strlen(dato) <= 0)
    {
        Utiles::printCOM("apn mal");
        return;
    }
    strcpy(apn, dato);
    Utiles::printCOM2("apn leida: ");
    Utiles::printCOM(apn);
}
void ArchivoConfig::leeTSD(char* buf)
{
    StringSplit sp(buf, "=");
    sp.get();
    char* dato = sp.get();
    if (strlen(dato) <= 0)
    {
        Utiles::printCOM("timer sd mal");
        return;
    }
    TimerSD = ((unsigned long)atoi(dato)) * 1000;
    Utiles::printCOM2("timerSD leida: ");
    Utiles::printCOM(dato);
}

void ArchivoConfig::leeTGPRS(char* buf)
{
    StringSplit sp(buf, "=");
    sp.get();
    char* dato = sp.get();
    if (strlen(dato) <= 0)
    {
        Utiles::printCOM("timer GPRS mal");
        return;
    }
    TimerGPRS = ((unsigned long)atoi(dato)) * 1000;
    Utiles::printCOM2("timerGPRS leida: ");
    Utiles::printCOM(dato);
}


void ArchivoConfig::leeTSMSD(char* buf)
{
    StringSplit sp(buf, "=");
    sp.get();
    char* dato = sp.get();
    if (strlen(dato) <= 0)
    {
        Utiles::printCOM("timer sms data mal");
        return;
    }
    TimerSMSData = ((unsigned long)atoi(dato)) * 1000;
    Utiles::printCOM2("timer sms data leida: ");
    Utiles::printCOM(dato);
}
void ArchivoConfig::leeTSMSI(char* buf)
{
    StringSplit sp(buf, "=");
    sp.get();
    char* dato = sp.get();
    if (strlen(dato) <= 0)
    {
        Utiles::printCOM("timer sms info mal");
        return;
    }
    TimerSMSInfo = ((unsigned long)atoi(dato)) * 1000;
    Utiles::printCOM2("timer sms info leida: ");
    Utiles::printCOM(dato);
}
void ArchivoConfig::leetlf(char* buf)
{
    n++;
    StringSplit sp(buf, ",");
    // telefono
    char* dato = sp.get();
    if (strlen(dato) < 9)
    {
        Utiles::printCOM("tlf mal");
        n--;
        return;
    }
    strcpy(tlf[n].tlf, dato);

    dato = sp.get();
    if (strlen(dato) < 1)
    {
        Utiles::printCOM("infoSMS mal");
        n--;
        return;

    }
    tlf[n].infoSMS = dato[0] == '1';

    dato = sp.get();
    if (strlen(dato) < 1)
    {
        Utiles::printCOM("dataSMS mal");
        n--;
        return;
    }
    tlf[n].dataSMS = dato[0] == '1';
    Utiles::printCOM(tlf[n].tlf);
}
char* ArchivoConfig::leeLinea(char*buf)
{
  int i = 0;
  while (file.available()) {
    buf[i] = file.read();
    if (buf[i] == '\n')
      break;
    else if (buf[i] != ' ' && buf[i] != '\r' )
      i++;
  }
  buf[i] = 0;
  return buf;
}
