#ifndef _PRINT_HELPERS_H_
#define _PRINT_HELPERS_H_

#include "parameters.h"
#include <stdio.h>

__inline void printdbg_data_bin(const char *filename, unsigned int *data,
                                unsigned int num_ints) {
  FILE *dump = fopen((const char *)filename, "wt");
  for (unsigned int i = 0; i < num_ints; i++) {
    unsigned int mask = 0x80000000;
    for (unsigned int j = 0; j < 32; j++) {
      if (data[i] & mask)
        fprintf(dump, "1"); // printf("1");
      else
        fprintf(dump, "0"); // printf("0");
      mask = mask >> 1;
    }
    fprintf(dump, "\n");
  }
  fclose(dump);
}
__inline void printdbg_data_int(const char *filename, unsigned int *data,
                                unsigned int num_ints) {
  FILE *dump = fopen((const char *)filename, "wt");
  for (unsigned int i = 0; i < num_ints; i++) {
    fprintf(dump, "%d: %d\n", i, data[i]);
  }
  fclose(dump);
}

__inline void printdbg_gpu_data_detailed(FILE *gpudump, unsigned int *cw32,
                                         unsigned int *cw32len,
                                         unsigned int *cw32idx,
                                         unsigned int num_elements) {
  for (unsigned int i = 0; i < num_elements; i++) {
    fprintf(gpudump, "bp: %d, kc: %d, startbit: %d, cwlen: %d, cw:\t\t",
            cw32idx[i], cw32idx[i] / 32, cw32idx[i] % 32, cw32len[i]);
    // print codeword:
    unsigned int mask = 0x80000000;
    mask = mask >> (32 - cw32len[i]);
    for (unsigned int j = 0; j < cw32len[i]; j++) {
      if (cw32[i] & mask)
        fprintf(gpudump, "1"); // printf("1");
      else
        fprintf(gpudump, "0"); // printf("0");
      mask = mask >> 1;
    }
    fprintf(gpudump, "\n");
  }
}

__inline void printdbg_gpu_data_detailed2(const char *filename,
                                          unsigned int *cw32,
                                          unsigned int *cw32len,
                                          unsigned int *cw32idx,
                                          unsigned int num_elements) {
  FILE *gpudump = fopen((const char *)filename, "wt");
  for (unsigned int i = 0; i < num_elements; i++) {
    fprintf(gpudump, "bp: %d, kc: %d, startbit: %d, cwlen: %d, cw:\t\t",
            cw32idx[i], cw32idx[i] / 32, cw32idx[i] % 32, cw32len[i]);
    // print codeword:
    unsigned int mask = 0x80000000;
    mask = mask >> (32 - cw32len[i]);
    for (unsigned int j = 0; j < cw32len[i]; j++) {
      if (cw32[i] & mask)
        fprintf(gpudump, "1"); // printf("1");
      else
        fprintf(gpudump, "0"); // printf("0");
      mask = mask >> 1;
    }
    fprintf(gpudump, "\n");
  }
  fclose(gpudump);
}

/************************************************************************/
/* BIT PRINTS                                                         */
/************************************************************************/
__inline void printBits(unsigned char number) {
  unsigned char mask = 0x80;
  for (unsigned int j = 0; j < 8; j++) {
    if (number & mask)
      printf("1");
    else
      printf("0");
    mask = mask >> 1;
  }
  printf(" ");
}
__inline void print32Bits(unsigned int number) {
  unsigned int mask = 0x80000000;
  for (unsigned int j = 0; j < 32; j++) {
    if (number & mask)
      printf("1");
    else
      printf("0");
    mask = mask >> 1;
  }
  printf("\n");
}
__inline void print32BitsM(unsigned int marker) {
  for (unsigned int j = 0; j < 32; j++) {
    if (marker == (j + 1))
      printf("|");
    else
      printf(".");
  }
  printf("\n");
}
__inline void print_array_char_as_bits(unsigned char *a, unsigned int len) {

  printf(
      " ========================= Printing vector =======================\n");
  printf("Total number of elements is %d\n", len);
  for (unsigned int i = 0; i < len; i++) {
    printf("a[%d]=%d \t", i, a[i]);
    printBits(a[i]);
    printf("\n");
  }
  printf("\n");
  printf(
      " ==================================================================\n");
}

__inline void print_array_ints_as_bits(unsigned int *a, unsigned int len) {

  printf(
      " ========================= Printing vector =======================\n");
  for (unsigned int i = 0; i < len; i++) {
    print32Bits(a[i]);
    printf("\n");
  }
  printf("\n");
  printf(
      " ==================================================================\n");
}

__inline void print_compare_array_ints_as_bits(unsigned int *a, unsigned int *b,
                                               unsigned int len) {

  printf(
      " ========================= Printing vector =======================\n");
  for (unsigned int i = 0; i < len; i++) {
    print32Bits(a[i]);
    print32Bits(b[i]);
    printf("\n");
  }
  printf("\n");
  printf(
      " ==================================================================\n");
}

__inline void print_array_in_hex(unsigned int *a, unsigned int len) {

  printf(
      " ========================= Printing vector =======================\n");
  // printf("Total number of elements is %d\n", len);
  for (unsigned int i = 0; i < len; i++) {
    printf("%#X\t", a[i]);
  }

  printf("\n");
  printf(
      " ==================================================================\n");
}

/************************************************************************/
/* ARRAY PRINTS                                                        */
/***********************************************************************/

template <typename T> __inline void print_array(T *a, unsigned int len) {

  printf(
      " ========================= Printing vector =======================\n");
  printf("Total number of elements is %d\n", len);
  for (unsigned int i = 0; i < len; i++) {
    printf("a[%d]=%d \t", i, a[i]);
  }

  printf("\n");
  printf(
      " ==================================================================\n");
}

template <typename ST, typename CT>
__inline void print_rled_arrays(ST *rle_symbols, CT *rle_counts,
                                unsigned int rle_len) {
  ST current_symbol;
  CT current_count;
  printf(" ========================= Printing RLE vector "
         "=======================\n");
  printf(" Total number of RL Pairs is %d\n", rle_len);
  for (unsigned int k = 0; k < rle_len; k++) {
    current_symbol = rle_symbols[k];
    current_count = rle_counts[k];
    printf("(%d,%d) ,\t", current_symbol, current_count);
  }
  printf("\n");
}

__inline void print_packed_rle_array(unsigned int *rle, unsigned int rle_len) {
  unsigned short current_symbol;
  unsigned short current_count;
  printf(" ========================= Printing RLE vector "
         "=======================\n");
  printf(" Total number of RL Pairs is %d\n", rle_len);
  for (unsigned int k = 0; k < rle_len; k++) {
    current_symbol = (unsigned short)(rle[k] >> 16); // get the higher half-word
    current_count =
        (unsigned short)rle[k] & 0x0000FFFFF; // get the shorter half-word
    printf("(%d,%d) ,\t", current_symbol, current_count);
  }
  printf("\n");
}

#endif // _PRINT_HELPERS_H_