#ifndef _MAG_MAGSTRIPE_H_
#define _MAG_MAGSTRIPE_H_

#include <stdint.h>
#include <sys/types.h>
#include <magbits.h>

/****************************************************************************************************************/

struct magcode {
  uint16_t mc_start;
  uint16_t mc_stop;
  uint16_t mc_offset;
  uint16_t mc_bits;
  uint32_t mc_flags;
};

/****************************************************************************************************************/

#ifdef __cplusplus
extern "C" {
#endif

extern const struct magcode mag_encodings[3];

/****************************************************************************************************************/
//
// Decode raw magstripe data.
//
// The decoder supports having the magstripe contain multiple copies of the same data.
// It returns the first fully decodable data found in the raw bitstream.
//
// When encountering a decode error, it continues searching for another start-sync and tries again
// until the raw data has been exhausted.
//
// On partial success, it returns the longest partially decodable block found.
//
// The decoder can parse the data in forward, reverse or both directions, configured through the «flags» parameter.
//
//   «enc»      -- Pointer to an encoding format definition
//                 For ISO standard, use predefined global variable mag_encodings[x]
//                 Track 1: &mag_encodings[0]
//                 Track 2: &mag_encodings[1]
//                 Track 3: &mag_encodings[2]
//
//  «data»      -- Raw data bitstream.
//                 Bit order is specified via the «flags» parameter, see there.
//
//  «len»       -- Number of bytes in «data»
//
//  «buf»       -- Buffer that receives the decoded data
//
//  «bufsize_p» -- [IN]  Points to a size_t that must contain the buffer size in bytes.
//                 [OUT] Function writes number of bytes returned.
//
//  «flags»     -- Flags controlling the decoder, binary or'ed.
//                 MAGFLAG_FORWARD   -- Decode in forward direction (Starting at first byte of bitstream)
//                 MAGFLAG_REVERSE   -- Decode in reverse direction (Starting at last byte of bitstream)
//                 MAGFLAG_MSB_FIRST -- On each byte, process MSB first (bit 7), then proceed down to LSB (bit 0)
//                                      (Default is to process LSB first and proceed upwards to bit 7)
//
//  Return value:
//    0 on success, one of the MAGERR_xxx error codes on decode failure.
//
//  When decode fails, the function still returns as many bytes of data that it could decode.
//  If return value is non-zero, but *bufsize_p is also non-zero, the function has done a partial decode.
//
int mag_decode(const struct magcode *enc, const void *data, size_t len, void *buf, size_t *bufsize_p, unsigned int flags);

/****************************************************************************************************************/
//
// Encode raw magstripe data.
//
//   «enc»      -- Pointer to an encoding format definition
//                 For ISO standard, use predefined global variable mag_encodings[x]
//                 Track 1: &mag_encodings[0]
//                 Track 2: &mag_encodings[1]
//                 Track 3: &mag_encodings[2]
//
//  «text»      -- ASCII text to encode.
//                 May or may not include start/stop/checksum byte.
//                 Whatever is missing will be added by the encoder.
//
//  «textlen»   -- Number of bytes in «text»
//
//  «buf»       -- Buffer that receives the raw bitstream
//                 Bit order is specified via the «flags» parameter, see there.
//
//  «bufsize_p» -- [IN]  Points to a size_t that must contain the buffer size in bytes.
//                 [OUT] Function writes number of bytes returned.
//
//
//  «flags»     -- Flags controlling the decoder, binary or'ed.
//                 MAGFLAG_MSB_FIRST -- On each byte, write MSB first (bit 7), then proceed down to LSB (bit 0)
//                                      (Default is to write LSB first and proceed upwards to bit 7)
//                 The data is always encoded in forward direction, the flags
//                 MAGFLAG_FORWARD and MAGFLAG_REVERSE have no effect.
//
//  Return value:
//    0 on success, one of the MAGERR_xxx error codes on decode failure.
//
int mag_encode(const struct magcode *enc, const char *text, size_t textlen, void *buf, size_t *bufsize_p, unsigned int flags);

/****************************************************************************************************************/

#ifdef __cplusplus
}
#endif

/****************************************************************************************************************/
#endif
