#include <iostream>
#include <iomanip>
#include <string>
#include <cstdlib>
#include <ctime>

#include "base64util.h"

void hexPrintString(std::string s)
{
  for (int i = 0; i < s.length(); i++)
    std::cout << std::hex << std::setw(2) << std::setfill('0') << unsigned(s[i] & 0xff);
}

void TestBase64()
{
  const int numberOfPasses = 100;
  const int minLength = 10;
  const int maxLength = 20;
  
  srandom(time(NULL));
  
  for (int i = 0; i < numberOfPasses; i++) {
    std::string s;
    int len = minLength + random() % (maxLength - minLength);
    for (int i = 0; i < len; i++)
      s += (unsigned char)(random() % 256);
#if 1
    hexPrintString(s);
    std::cout << "  " << EncodeBase64(s) << "  ";
    hexPrintString(DecodeBase64(EncodeBase64(s)));
    std::cout << std::endl;
#endif
    if (DecodeBase64(EncodeBase64(s)) != s)
      std::cout << "##### Failed: " << s << std::endl;    
  }
}

void TestBase32()
{
  const int numberOfPasses = 100;
  const int minLength = 10;
  const int maxLength = 20;
  
  srandom(time(NULL));
  
  for (int i = 0; i < numberOfPasses; i++) {
    std::string s;
    int len = minLength + random() % (maxLength - minLength);
    for (int i = 0; i < len; i++)
      s += (unsigned char)(random() % 256);
#if 1
    hexPrintString(s);
    std::cout << "  " << EncodeBase32(s) << "  ";
    hexPrintString(DecodeBase32(EncodeBase32(s)));
    std::cout << std::endl;
#endif
    if (DecodeBase64(EncodeBase64(s)) != s)
      std::cout << "##### Failed: " << s << std::endl;    
  }
}

int main (int argc, char * const argv[])
{
#if 0
  TestBase64();
#endif
  
#if 0
  TestBase32();
#endif
  
#if 1
  try {
    hexPrintString(DecodeBase64("8Phid3CSe+UcVg=="));
    std::cout << std::endl;
  }
  catch (std::exception &e) {
    std::cout << "Exception: " << e.what() << std::endl;
  }  

  try {
    hexPrintString(DecodeBase64("8Phid3CSe+UcVg==="));
    std::cout << std::endl;
  }
  catch (std::exception &e) {
    std::cout << "Exception: " << e.what() << std::endl;
  }  
  
  try {
    hexPrintString(DecodeBase64("8Phid3CSe=UcVg=="));
    std::cout << std::endl;
  }
  catch (std::exception &e) {
    std::cout << "Exception: " << e.what() << std::endl;
  }  
  
  try {
    hexPrintString(DecodeBase32("L3LFNDU3CJOVXVMZRU======"));
    std::cout << std::endl;
  }
  catch (std::exception &e) {
    std::cout << "Exception: " << e.what() << std::endl;
  }  
  
  try {
    hexPrintString(DecodeBase32("L3LFNDU3CJOVXVMZRU========"));
    std::cout << std::endl;
  }
  catch (std::exception &e) {
    std::cout << "Exception: " << e.what() << std::endl;
  }  
  
  try {
    hexPrintString(DecodeBase32("L3LFNDU3CJOVX=MZRU======"));
    std::cout << std::endl;
  }
  catch (std::exception &e) {
    std::cout << "Exception: " << e.what() << std::endl;
  }  
#endif
  
#if 0
  std::string s = "Hello, World!";
  
  std::cout << EncodeBase64(s) << std::endl;
  
  std::cout << DecodeBase64(EncodeBase64(s)) << std::endl;  

  std::cout << EncodeBase32(s) << std::endl;
  
  std::cout << DecodeBase32(EncodeBase32(s)) << std::endl;  
#endif
  
  return 0;
}

