#pragma once

#include <stdio.h>
#include <stdarg.h>

//a template class for a fixed length buffer class.
template <int buffer_len>
class CBuffer {
  public:
    CBuffer();
    //pass parametes like printf
    CBuffer(const char *format_string, ...);

    //sets the string.  pass parameters like printf.
    void Set(const char *format_string, ...);

    //returns the name as a null terminated string.
    operator const char *() const;

    //returns true if the string is non-empty.
    operator bool() const;

    //copies the given null-terminated string.  NULL or empty strings set the buffer to ""
    const char *operator=(const char *str);

    void Save(FILE *file) const;
    void Load(FILE *file, int version);

  protected:
    char buffer[buffer_len];
};

template <int buffer_len>
CBuffer<buffer_len>::CBuffer() {
    buffer[0] = '\0';
}

template <int buffer_len>
CBuffer<buffer_len>::CBuffer(const char *format_string, ...) {
    //get our parameter list.
    va_list args;
    va_start(args, format_string);

    //call _vsnprintf
    _vsnprintf(buffer, buffer_len, format_string, args);

    //put a null at the end.
    buffer[buffer_len - 1] = '\0';
}

template <int buffer_len>
void CBuffer<buffer_len>::Set(const char *format_string, ...) {
    //get our parameter list.
    va_list args;
    va_start(args, format_string);

    //call _vsnprintf
    _vsnprintf(buffer, buffer_len, format_string, args);

    //put a null at the end.
    buffer[buffer_len - 1] = '\0';
}

template <int buffer_len>
CBuffer<buffer_len>::operator const char *() const {
    return buffer;
}

template <int buffer_len>
CBuffer<buffer_len>::operator bool() const {
    return buffer[0] != '\0';
}

template <int buffer_len>
const char *CBuffer<buffer_len>::operator=(const char *str) {
    if (str == NULL || str[0] == '\0') {
        buffer[0] = '\0';
        return buffer;
    }

    //copy the string, converting to lower case.
    strncpy(buffer, str, buffer_len - 1);

    //make the last character null.
    buffer[buffer_len - 1] = '\0';

    return buffer;
}

template <int buffer_len>
void CBuffer<buffer_len>::Save(FILE *file) const {
    fwrite(&buffer[0], buffer_len, 1, file);
}

template <int buffer_len>
void CBuffer<buffer_len>::Load(FILE *file, int version) {
    fread(&buffer[0], buffer_len, 1, file);
}

//some buffer types.
typedef CBuffer<16> buffer16;
typedef CBuffer<32> buffer32;
typedef CBuffer<64> buffer64;
typedef CBuffer<128> buffer128;
typedef CBuffer<256> buffer256;


