#include <stdint.h>
#include <stdio.h>

#include "../lib/rsa.h"

char *int128_to_str(__int128_t n) {
  static char str[41] = {0};
  char *s = str + sizeof(str) - 1;
  bool neg = n < 0;
  if (neg)
    n = -n;
  do {
    *--s = "0123456789"[n % 10];
    n /= 10;
  } while (n);
  if (neg)
    *--s = '-';
  return s;
}

int main() {
  uint64_t p0 = 8589934609, q0 = 2147483693, e0 = 65537;
  uint64_t p1 = 2147483659, q1 = 8589934621, e1 = 65537;

  rsa_Pair pair_0 = rsa_gen_pair(p0, q0, e0);
  rsa_Pair pair_1 = rsa_gen_pair(p1, q1, e1);

  printf("pair_0:\n");
  printf("- e:\t%s\n", int128_to_str(pair_0.e));
  printf("- d:\t%s\n", int128_to_str(pair_0.d));
  printf("- n:\t%s\n", int128_to_str(pair_0.n));

  printf("pair_1:\n");
  printf("- e:\t%s\n", int128_to_str(pair_1.e));
  printf("- d:\t%s\n", int128_to_str(pair_1.d));
  printf("- n:\t%s\n", int128_to_str(pair_1.n));

  uint64_t t[] = {22, 17, 2, 65500, 0x9fffffff};

  for (size_t i = 0; i < 5; i++) {
    printf("- - - - - - - - - - - - - - - - - -\n");

    printf("t[%zu]:\t\t%lld\n", i, t[i]);

    __int128_t e1t = rsa_encrypt(t[i], pair_0.e, pair_0.n);
    printf("e1t:\t\t%s\n", int128_to_str(e1t));

    __int128_t d1e1t = rsa_decrypt(e1t, pair_0.d, pair_0.n);
    printf("d1e1t:\t\t%s\n", int128_to_str(d1e1t));

    if (d1e1t != t[i]) {
      fprintf(stderr, "Error: decrypt[i]on failed - expected: %llu; got: %s\n",
              t[i], int128_to_str(d1e1t));
      return 1;
    }

    __int128_t e0d1e1t = rsa_encrypt(t[i], pair_1.e, pair_1.n);
    printf("e0d1e1t:\t%s\n", int128_to_str(e0d1e1t));

    __int128_t d0e0d1e1t = rsa_decrypt(e0d1e1t, pair_1.d, pair_1.n);
    printf("d0e0d1e1t:\t%s\n", int128_to_str(d0e0d1e1t));

    if (d0e0d1e1t != t[i]) {
      fprintf(stderr, "Error: decrypt[i]on failed - expected: %llu; got: %s\n",
              t[i], int128_to_str(d0e0d1e1t));
      return 1;
    }
  }

  return 0;
}
