#include "mbedtls/aes.h"
#include "SPIFFSTest.h"
#include "Cipher.h"

CSPIFFS mSpiffs;
Cipher * cipher = new Cipher();


String encryptBuffer(char * plainText, char * key) {
  // returns encrypted String of plainText (length: 16 characters)
  String cipherTextString = "1234567890123456";
  
  // encrypt plainText buffer of length 16 characters
  mbedtls_aes_context aes;
 
  mbedtls_aes_init( &aes );
  mbedtls_aes_setkey_enc( &aes, (const unsigned char*) key, strlen(key) * 8 );
  mbedtls_aes_crypt_ecb( &aes, MBEDTLS_AES_ENCRYPT, (const unsigned char*)plainText, (unsigned char*) cipherTextString.c_str());
  mbedtls_aes_free( &aes );

  return cipherTextString;
}

String encryptString(String plainText, char * key) {
  // returns encrypted String of plainText with variable length
  constexpr int BUFF_SIZE=16;
  String buffer = "";
  String cipherTextString = "";
  int index = plainText.length() / BUFF_SIZE;
  
  for(int block=0; block < plainText.length()/BUFF_SIZE; block++) {
      for(int j = block*BUFF_SIZE; j < (block+1)*BUFF_SIZE; j++) {
        buffer += plainText[j];
      }
      
      cipherTextString += encryptBuffer(const_cast<char*>(buffer.c_str()), key);
      buffer = "";
  }

  buffer="";

  if( plainText.length()%BUFF_SIZE > 0 ) {    
    for(int bytes_read=(index*BUFF_SIZE); bytes_read <= (index*BUFF_SIZE) + plainText.length()%BUFF_SIZE; bytes_read++) {
      buffer += plainText[bytes_read];
    };
    cipherTextString += encryptBuffer(const_cast<char*>(buffer.c_str()), key);
  }

  return cipherTextString;
}

String decryptBuffer(String cipherText, char * key) {
  // returns decrypted String of ciphered text (length: 16 characters)
  String decipheredTextString = "1234567890123456";

  // encrypt ciphered chipherText buffer of length 16 characters to plain text
  mbedtls_aes_context aes;
 
  mbedtls_aes_init( &aes );
  mbedtls_aes_setkey_dec( &aes, (const unsigned char*) key, strlen(key) * 8 );
  mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_DECRYPT, (const unsigned char*)cipherText.c_str(), (unsigned char*) decipheredTextString.c_str());
  mbedtls_aes_free( &aes );

  // removes eventually \0 inside
  decipheredTextString = String(decipheredTextString.c_str());
  return decipheredTextString;
}


String decryptString(String cipherText, char * key) {
  // returns encrypted String of plainText with variable length
  constexpr int BUFF_SIZE=16;
  String buffer = "";
  String decipheredTextString = "";
  
  for(int block=0; block < cipherText.length()/BUFF_SIZE; block++) {
      for(int j = block*BUFF_SIZE; j < (block+1)*BUFF_SIZE; j++) {
        buffer += cipherText[j];
      }
      
      decipheredTextString += decryptBuffer(buffer, key);
      buffer = "";
  }

  return decipheredTextString;
}

void setup() {
 
  Serial.begin(115200);
  
  SPIFFS.begin(true);
  mSpiffs.listDir(SPIFFS, "/", 0);
  
  char * key = "abcdefghijklmnop";
  String plainText = "Tech tutorials xTech tutorials xxyzgvszufsdgftzsdfgsdfzfsfdzfsdzfsdtzfdtzsfdtzsfdtzfsdtzfstzfzsfdfzs";

  Serial.print("\nSetting cipher key: ");
  Serial.println(key);
  cipher->setKey(key);

  Serial.println("\nOriginal plain text:");
  Serial.println(plainText);

  Serial.println("\nCiphered text:");
  String text = cipher->encryptString(plainText);
  Serial.println(text);
  //mSpiffs.writeFile(SPIFFS, "/test.txt", text);

  //Serial.println("\nDeciphered text:");
  //Serial.println(cipher->decryptString(mSpiffs.getFile(SPIFFS, "/test.txt")));
  Serial.println(cipher->decryptString(text));



// traditional methods, no library

  String s = encryptString(plainText, key);
  Serial.println(s);

  Serial.println(decryptString(s, key));

}
 
void loop() {
  
}
esp:0
esp:2
esp:4
esp:5
esp:12
esp:13
esp:14
esp:15
esp:16
esp:17
esp:18
esp:19
esp:21
esp:22
esp:23
esp:25
esp:26
esp:27
esp:32
esp:33
esp:34
esp:35
esp:3V3
esp:EN
esp:VP
esp:VN
esp:GND.1
esp:D2
esp:D3
esp:CMD
esp:5V
esp:GND.2
esp:TX
esp:RX
esp:GND.3
esp:D1
esp:D0
esp:CLK