#include"SDmanger.h"
File Comenfile;

int sdcard::init_sdcard()
{
  SD_MMC.setPins(9,10,11,12,13,14);
  int succ = SD_MMC.begin("/sdcard", true,true,20000);
  if (succ) {
    // Serial.printf("SD_MMC Begin: %d\n", succ);
    write_log(log_path,"SD_MMC Begin: "+String(succ),10);
    uint8_t cardType = SD_MMC.cardType();
    // Serial.print("SD_MMC Card Type: ");uj
    write_log(log_path,"SD_MMC Card Type: ",10);
    if (cardType == CARD_MMC) {
      // Serial.println("MMC");
      write_log(log_path,"MMC",10);
    } else if (cardType == CARD_SD) {
      // Serial.println("SDSC");
      write_log(log_path,"SDSC",10);
    } else if (cardType == CARD_SDHC) {
      // Serial.println("SDHC");
      write_log(log_path,"SDHC",10);
    } else {
      // Serial.println("UNKNOWN");
      write_log(log_path,"UNKNOWN",10);
    }

    uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024);
    uint32_t c  = cardSize;
    // Serial.printf("SD_MMC Card Size: %lluMB\n", cardSize);
    write_log(log_path,"SD_MMC Card Size: "+String(c)+"MB",10);

    // Serial.printf("Total space: %lluMB\n", SD_MMC.totalBytes() / (1024 * 1024));
    float a = SD_MMC.totalBytes() / (1024 * 1024);
    write_log(log_path,"Total space: "+String(a)+"MB",10);
    // Serial.printf("Used space: %lluMB\n", SD_MMC.usedBytes() / (1024 * 1024));
    a = SD_MMC.usedBytes() / (1024 * 1024);
    write_log(log_path,"Used space: "+String(a)+"MB",10);

    mylistDir( "/", 0);
    // File file;

    // file.listFiles("/");
    // file.flush();
    // file.close();

  } else {
    // Serial.printf("Failed to mount SD card VFAT filesystem. \n");
    write_log(log_path,"Failed to mount SD card VFAT filesystem. ",10);
    // Serial.println("Do you have an SD Card installed?");
    write_log(log_path,"Do you have an SD Card installed?",10);
    // Serial.println("Check pin 12 and 13, not grounded, or grounded with 10k resistors!\n\n");
    write_log(log_path,"Check pin 12 and 13, not grounded, or grounded with 10k resistors!\n\n",10);
   // major_fail();
  }

  return ESP_OK;
}

 void sdcard::mylistDir( const char * dirname, uint8_t levels) {
  write_log(log_path,"Listing directory: "+String(dirname),10);
  String dir(dirname);
  File root = SD_MMC.open(dirname);
  if (!root) {
    write_log(log_path,"Failed to open directory",10);
    return;
  }
  if (!root.isDirectory()) {
    write_log(log_path,"Not a directory",10);
    return;
  }

  File filex = root.openNextFile();
  while (filex) {
    if (filex.isDirectory()) 
    {
      write_log(log_path,"  DIR : " + String(filex.name()),10);
      if (levels) {
        String filename=dir+"/"+String(filex.name());
        mylistDir( filename.c_str(), levels - 1);
      }
    } 
    else
    {
      write_log(log_path,"  FILE: " + String(filex.name()) + " size :"+ String(filex.size()) + "B",10);
    }
    filex = root.openNextFile();
  }
}
bool sdcard::ListDir(const char * dirname,Vector <String> &stringlist)
{
  stringlist.clear();
  // Serial.printf("Listing directory: %s\n",  dirname);
  write_log(log_path,"Listing directory: "+String(dirname),10);
  String dir(dirname);
  File root = SD_MMC.open(dirname);
  if (!root) {
    // Serial.println("Failed to open directory");
    write_log(log_path,"Failed to open directory",10);
     return true;
  }
  if (!root.isDirectory()) {
    // Serial.println("Not a directory");
    write_log(log_path,"Not a directory",10);
      return true;
  }

  File filex = root.openNextFile();
  while (filex) 
  {
    if (filex.isDirectory()) {
    
    } else {
      String filename=dir+"/"+String(filex.name());
      stringlist.push_back(filename);
     
      if (stringlist.size()==stringlist.max_size())
      {
          return false;
        /* code */
      }
      
    }
    filex = root.openNextFile();
  }

  return true;
}


 void sdcard::delete_old_stuff() {

  // Serial.printf("Total space: %lluMB\n", SD_MMC.totalBytes() / (1024 * 1024));
  float a = SD_MMC.totalBytes() / (1024 * 1024);
  write_log(log_path,"Total space: "+String(a)+"MB",10);
  // Serial.printf("Used space: %lluMB\n", SD_MMC.usedBytes() / (1024 * 1024));
  a = SD_MMC.usedBytes() / (1024 * 1024);
  write_log(log_path,"Used space: "+String(a)+"MB",10);
  //listDir( "/", 0);

  float full = 1.0 * SD_MMC.usedBytes() / SD_MMC.totalBytes();;
  if (full  <  0.8) {
    // Serial.printf("Nothing deleted, %.1f%% disk full\n", 100.0 * full);
    write_log(log_path,"Nothing deleted, "+String(100.0 * full)+"% disk full",10);
  } else {
    // Serial.printf("Disk is %.1f%% full ... deleting oldest file\n", 100.0 * full);
    write_log(log_path,"Disk is "+String(100.0 * full)+"% full ... deleting oldest file",10);
    while (full > 0.8) {

      double del_number = 999999999;
      char del_numbername[50];

      File f = SD_MMC.open("/");

      File file = f.openNextFile();

      while (file) {
        //Serial.println(file.name());
        if (!file.isDirectory()) {

          char foldname[50];
          strcpy(foldname, file.name());
          for ( int x = 0; x < 50; x++) {
            if ( (foldname[x] >= 0x30 && foldname[x] <= 0x39) || foldname[x] == 0x2E) {
            } else {
              if (foldname[x] != 0) foldname[x] = 0x20;
            }
          }

          double i = atof(foldname);
          if ( i > 0 && i < del_number) {
            strcpy (del_numbername, file.name());
            del_number = i;
          }
          //Serial.printf("Name is %s, number is %f\n", foldname, i);
        }
        file = f.openNextFile();

      }
      // Serial.printf("lowest is Name is %s, number is %f\n", del_numbername, del_number);
      write_log(log_path,"lowest is Name is "+String(del_numbername)+", number is "+String(del_number),10);
      if (del_number < 999999999) {
        deleteFolderOrFile(del_numbername);
      }
      full = 1.0 * SD_MMC.usedBytes() / SD_MMC.totalBytes();
      // Serial.printf("Disk is %.1f%% full ... \n", 100.0 * full);
      write_log(log_path,"Disk is "+String(100.0 * full)+"% full ... ",10);
      f.close();
    }
  }
}

 void sdcard::deleteFolderOrFile(const char * val) {
  write_log(log_path,"Deleting : "+String(val),10);
  File f = SD_MMC.open(val);
  if (!f) {
    write_log(log_path,"Failed to open "+String(val),10);
    return;
  }

  if (f.isDirectory()) {
    File file = f.openNextFile();
    while (file) {
      if (file.isDirectory()) {
        write_log(log_path,"  DIR : ",10);
        write_log(log_path,file.name(),10);
      } else {
        write_log(log_path,"  FILE: ",10);
        write_log(log_path,file.name(),10);
        write_log(log_path,"  SIZE: ",10);
        write_log(log_path,String(file.size()),10);
        if (SD_MMC.remove(file.name())) {
          write_log(log_path," deleted.",10);
        } else {
          write_log(log_path," FAILED.",10);
        }
      }
      file = f.openNextFile();
    }
    f.close();
    if (SD_MMC.rmdir(val)) {
      write_log(log_path,"Dir "+String(val)+" removed",10);
    } else {
      write_log(log_path,"Remove dir failed",10);
    }

  } else {
    //Remove the file
    if (SD_MMC.remove(val)) {
      write_log(log_path,"File "+String(val)+" deleted",10);
    } else {
      write_log(log_path,"Delete failed",10);
    }
  }
}

 void sdcard:: testwriet()
{
    File file;
      file = SD_MMC.open("/try.txt", "wb");
      file.println("hello world");
      file.flush();
      file.close();
}



  void sdcard::WriteStringToFile(String name,String Str)
  {
      File file;

      file = SD_MMC.open(name, "w+");
      file.println(Str);
      file.flush();
      file.close();
  }
    void sdcard::WriteStringToFile(String name,char *data,size_t lenth)
  {
      File file;

      file = SD_MMC.open(name, "wb");
      file.write((const byte *)data,lenth);
      file.flush();
      file.close();
  }
 bool sdcard::Mkdir(String path)
  {
     return SD_MMC.mkdir(path);
  }

namespace sdcard
{
  void openFileformWirte(String Path)
  {
    if (Comenfile.available())
    {
      Comenfile.close();
      /* code */
    }
    Comenfile = SD_MMC.open(Path, "w+");
  
  }
  
  void WritetoFileCommen(String Str)
  {
    if (Comenfile.available())
    {
      Comenfile.print(Str);
      Comenfile.flush();
      /* code */
    }
  }
  
  void WritetoFileCommen(char *data,size_t lenth)
  {
    if (Comenfile.available())
    {
      Comenfile.write((const byte *)data,lenth);
      Comenfile.flush();
      /* code */
    }
    
  }
  
  void closeCommenFile()
  {
    if (Comenfile.available())
    {
      Comenfile.close();
      /* code */
    }
    
  }
}