#include <stdlib.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <limits.h>   
#include <stdint.h>   
#include <inttypes.h> 
#include <time.h>

#define SIZE_CHAR
#define WAIT_TIME 500000000 // in nanoseconds
#define NB_OF_THREADS 4

/** binary representation of input v */
int binprn(const uint64_t v, char *str) {
  int cpt = 0;
  if (!v) {
    putchar('0');
    return 0;
  }; 

  size_t sz = sizeof v * CHAR_BIT; 
  uint64_t rem = 0; 

  while (sz--)                            
    if ((rem = v >> sz))                  
      str[cpt++] = (rem & 1) ? '1' : '0'; 

  return cpt;
}



void *t1(void *arg) {
  int cpt;
  for (long i = 0; i < 300000000; i++) {
    cpt = (cpt + 10);
  }
  return arg;
}

void waitFor(int millis) {
  struct timespec sleep_time, remaining_time;

  sleep_time.tv_sec = 0;
  sleep_time.tv_nsec = millis;

  // Call nanosleep
  int result = nanosleep(&sleep_time, &remaining_time);

  if (result == 0) {
    printf("Slept for %d milliseconds.\n", WAIT_TIME / 1000000);
  } else {
    printf("nanosleep was interrupted. Remaining time: %ld seconds, %ld nanoseconds.\n",
    remaining_time.tv_sec, remaining_time.tv_nsec);
  }
}

void compute(int value) {
  printf("Computing %d \n", value);
  pthread_t tid[NB_OF_THREADS];
  int threads;

  if (value == 0) {
    threads = NB_OF_THREADS / 4;
  } else {
    threads = NB_OF_THREADS;
  }
  printf("Using %d threads\n", threads);
  for (int j = 0; j < threads; j++) {
    pthread_create(&tid[j], NULL, t1, NULL);
  }

  for (int j = 0; j < threads; j++) {
    pthread_join(tid[j], NULL);
  }

  waitFor(WAIT_TIME);
}

int main(int argc, char **argv) {

  if (argc < 2) {
    printf("usage: compute <text to be sent>\n");
    exit(1);
  }

  printf("Sleeping\n");
  sleep(10);

  printf("Running\n");

  while (1) {
    int k = 0;
    int i;
    while (argv[1][k] != '\0') { // Handling each character one by one
      printf("Handling %c \n", argv[1][k]);

      char *str = (char *)(malloc(sizeof(char) * 9));
      for (i = 0; i < 9; i++) {
        str[i] = '\0';
      }
      
      int cpt = binprn(argv[1][k], str); // binary representation

      int dec = 8 - cpt; //padding
      if (dec > 0) {
        for (i = 8 - dec; i >= 0; i--) {
          str[i + dec] = str[i];
          str[i] = '0';
        }
      }

      printf("%s\n", str);

      int l;
      for (l = 0; l < 8; l++) {
        printf("Handling: %d ", str[l]);
        if (str[l] == '0') {
          compute(0);
        } else {
          compute(1);
        }
      }
      k++;
    }

    sleep(5);
  }

  return (0);
}
