#ifndef __TIF_FUNCS__
#define __TIF_FUNCS__

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

#define TIF_TAPE_HEADER_LENGTH        128
#define TIF_HEADER_BLOCK_LENGTH_18    576  /* 18*32 */
#define TIF_HEADER_BLOCK_LENGTH_19    608  /* 19*32 */
#define TIF_HEADER_BLOCK_LENGTH_20    640  /* 20*32 */
#define TIF_HEADER_BLOCK_LENGTH_21    672  /* 21*32 */
#define TIF_HEADER_BLOCK_LENGTH_22    704  /* 22*32 */
#define TIF_DATA_BLOCK_LENGTH     3691200  /* 240*(20+6144*2.5) */

// used to identify errors
#define TIF_ERROR_EOF                   1
#define TIF_ERROR_READING	        2
#define TIF_ERROR_UNKNOWN_ID            3
#define TIF_ERROR_MISSING_BLOCK_END     4
#define TIF_ERROR_INCORRECT_END         5

int tif_error=0;


// extern char* tif_read_block(FILE *fp, long &len);


/*
  Function that reads 4 bytes and calculates block-length

  Returns length on success and -1 on error
*/
long tif_read_block_length(FILE *fp) {
  unsigned int block_len;
  unsigned char c[4];

  if (feof(fp)) {
    tif_error = TIF_ERROR_EOF;
    return -1;
  }

  for (int x=0;x<4;x++)
    if (fread(&c[x], 1, 1, fp) != 1) {
      if (feof(fp))
        tif_error = TIF_ERROR_EOF;
      if (ferror(fp))
        tif_error = TIF_ERROR_READING;


      return -1;
    }

  block_len = (c[0]*256+c[1])*(c[2]*256+c[3])/256;
  /* fprintf(stderr,"block length: %d\n",block_len); */

  return block_len;
}


/*
  Function that reads block data (the data between the 4 byte markers)

  Returns 0 on success and -1 on error

  buffer is where the data is put
  len is how much data to put in buffer
*/
int tif_read_block_data(FILE *fp, char *buffer, long len) {
  if (feof(fp)) {
    tif_error = TIF_ERROR_EOF;
    return -1;
  }

  if (fread(buffer, len, 1, fp) != 1) {
     if (feof(fp))
       tif_error = TIF_ERROR_EOF;
     if (ferror(fp))
       tif_error = TIF_ERROR_READING;
     return -1;
  }

  return 0;
}


/*
  Function that reads an entire block, and returns data and length of block

  Returns NULL if error, or if block is empty
  Returns block of data on success

  len returns the length of the block
*/
char* tif_read_block(FILE *fp, long &len) {
  int l1, l2; // length-marker on beginning and end of block
  char *t;  // pointer to databuffer

  l1 = tif_read_block_length(fp);

  // if error occured
  if (l1<0) {
    len = -1;
    return NULL;
  }

  // if block length = 0, block is a file-separator
  if (l1==0) {
    len = 0;
    l2 = tif_read_block_length(fp);
    if (l1 != l2) {
      len = -1;
      tif_error = TIF_ERROR_MISSING_BLOCK_END;
    }
    return NULL;
  }

  // block length is more than 0, figure out datalength

  t = (char *)malloc(sizeof(char) * l1);
  if (tif_read_block_data(fp, t, l1)!=0) {
    free(t);
    t = NULL;
    len = -1;
    return NULL;
  }

  // successful reading, read and check end-block, 4 bytes
  l2 = tif_read_block_length(fp);

  // length not the same, error occured
  if (l1!=l2) {
    free(t);
    t = NULL;
    len = -1;
    tif_error = TIF_ERROR_INCORRECT_END;
    return NULL;
  }

  // length the same, return temp;
  len = l1;
  return t;
}




#endif // __TIF_FUNCS__