#include "apoconv.h"
#include "apoheader.h"
#include <helper.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

uint8_t apo_data_header_print (uint8_t* ptr, char* file, size_t size) {
  unsigned int i = 0;
  uint8_t count = ptr[size-1];

  /* print the header */
  fprintf(stdout,"File: %s\n",file);  
  fprintf(stdout,"Full header: ");
  for (; i < size; ++i) fprintf(stdout,"0x%02x ",ptr[i]);
  fprintf(stdout,"\n");
  fprintf(stdout,"Serial: 0x%04x\n",letohs(PTR16(ptr)[0]));
  fprintf(stdout,"Count: %u\n",count);
  return count;
}

void apo_data_decode_file (char* file, size_t headersize) {
  struct mmapped_file apo;
  unsigned int i = 0;
  void* ptr;
  uint16_t descr;
  uint8_t count = 0;
  struct apo_entry_func* funcs;

  
  if (mem_map(file,&apo) < 0) {
    fprintf(stderr,"Failed to open %s\n",file);
    exit(EXIT_FAILURE);
  }

  count = apo_data_header_print(PTR8(apo.ptr),file,headersize);

  i = 0;
  for (ptr = PTR8(apo.ptr)+headersize; PTR8(ptr) < PTR8(apo.ptr)+apo.size; ptr = apo_get_next_header(ptr,apo.ptr)) {
    descr = letohs(PTR16(ptr)[0]);
    fprintf(stdout,"Field: 0x%02x at 0x%04lx",descr,(long)ptr-(long)apo.ptr);
    fprintf(stdout," (%s)",apo_get_description(descr));
    funcs = apo_get_entry_funcs (descr);
    if (funcs && funcs->printText) {
      fprintf(stdout,": ");
      funcs->printText(apo_header_align(ptr,apo.ptr),stdout);
    }
    fprintf(stdout,"\n");
    ++i;
  }
  fprintf(stdout,"\n");
  if (i != count) {
    fprintf(stdout,"Count check failed: %u != %u\n",i,count);
    exit(EXIT_FAILURE+1);
  }
}

void apo_data_decode (struct apo_main_info* info) {
  size_t hsize = 0;

  switch (info->version) {
  case 1:
    hsize = 6;
    apo_header_init(APO_S55);
    break;
  case 2:
    hsize = 6;
    apo_header_init(APO_S65);
    break;
  case 3:
    hsize = 10;
    apo_header_init(APO_SL75);
    break;
  default:
    return;
  }
  
  for (; info->files != NULL; info->files = info->files->next)
    apo_data_decode_file(info->files->data,hsize);
}
