/* ------------------- vecin2.c ------------------------

  Load a vector graphic from a VEC or VE2 file.

  ---------------------------------------------------- */

#include <stdio.h>
#include <string.h>
#include "vecin2.h"

#define BufSize 128

uint8_t fbuf[BufSize];
uint8_t fbufidx;
size_t recsread;
FILE *vecfile;
VE2Header header;


// DEBUG >>>
/*
void dumpfbuf() {
    int i;
    int cnt;
    
    cnt = 0;
    for (i = 0; i < BufSize; i++) {
        printf("%2x ", fbuf[i]);
        cnt++;
        if (cnt > 0x0F) {
            cnt = 0;
            putchar('\n');
        }
    }
    printf("ENDE\n");
    getchar();
}
*/
// <<< DEBUG


/* Reads a byte from the buffer. Reads a block from disc
   as soon as the buffer is read to the end. */
uint8_t readBuf() {
    if (fbufidx == BufSize - 1) {
        fbufidx = 0;
        recsread = fread(fbuf, BufSize, 1, vecfile); // reads a block of 128 bytes
        //dumpfbuf(); // DEBUG
    }
    else {
        fbufidx++;
    }
  
    return fbuf[fbufidx];
}


// Opens a VEC file.
errorCode_t openVecFile(const char *filename) {
    errorCode_t result;

    fbufidx = BufSize - 1;
    vecfile = fopen(filename, "rb");
    if (vecfile == NULL) {
        result = ErrFileNotFound;
    }
    else {
        result = ErrOk;
    }
  
    return result;
}


// Closes the VEC/VE2 file previously opened.
void closeVecFile() {
    fclose(vecfile);
}


/* Reads and verifies the vector graphics file ident (should be "VEC" or "VE2").
   Returns the vector file type: 0=unknown, 1=VEC, 2=VE2 */
uint8_t readFileType() {
    char sType[4];
    uint8_t fileType;

    fileType = 0;
    sType[0] = readBuf();
    sType[1] = readBuf();
    sType[2] = readBuf();
    sType[3] = '\0';
    
    if (strcmp("VEC", sType) == 0) {
        fileType = 1; // VEC
        header.bytesXCoord = 2; // fixed size
        header.bytesYCoord = 2; // fixed size
    }
    else if (strcmp("VE2", sType) == 0) {
        fileType = 2; // VE2
    }

    return fileType;
}


// Reads a VE2 header.
VE2Header *readVe2Header() {
    header.minX = readValue();
    header.maxX = readValue();
    header.minY = readValue();
    header.maxY = readValue();
    header.targetResolutionX = readValue();
    header.targetResolutionY = readValue();
    header.bytesXCoord = readBuf();
    header.bytesYCoord = readBuf();
    header.profileFlags = readValue();
    
    return &header;
}


// Reads the vector graphics operation code.
uint8_t readOpCode() {
  return readBuf();
}


// Reads the vector graphics operation's dot count.
uint8_t readDotCount() {
  return readBuf();
}


// Reads a two-byte value (coordinate, width, radius, etc.).
int readValue() {
    uint8_t b;
    int i;

    b = readBuf();
    i = b;
    b = readBuf();
    i += b << 8;
    
    return i;
}


// Reads an X coordinate; input size depends on bytesXCoord.
int readX() {
    int result;

    if (header.bytesXCoord == 1) {
        result = readBuf();   // 1 Byte
    }
    else {
        result = readValue(); // 2 Bytes
    }
    
    return result;
}


// Reads a Y coordinate; input size depends on bytesYCoord.
int readY() {
    int result;

    if (header.bytesYCoord == 1) {
        result = readBuf();   // 1 Byte
    }
    else {
        result = readValue(); // 2 Bytes
    }
    
    return result;
}


/* Reads a value; input size depends on the maximum of bytesXCoord
   and bytesYCoord. */
int readMax() {
    int result;
    uint8_t maxSize;

    maxSize = header.bytesXCoord;
    if (header.bytesYCoord > maxSize) {
        maxSize = header.bytesYCoord;
    }
    if (maxSize == 1) {
        result = readBuf();   // 1 Byte
    }
    else {
        result = readValue(); // 2 Bytes
    }
    
    return result;
}
