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

    tsv.c

    functions for TSV file handling.

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

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include "driver.h"
#include "config.h"
#include "misc.h"
#include "tsv.h"

#ifdef JAPANESE
 #ifdef NEOMAME
  #define TSVNAME "neomame32j.lst"
 #else
  #ifdef CPSMAME
   #define TSVNAME "cpsmame32j.lst"
  #else
   #ifdef TINY_COMPILE
     #define TSVNAME "tinymame32j.lst"
   #else
     #define TSVNAME "mame32j.lst"
   #endif
  #endif
 #endif
#else
 #ifdef NEOMAME
  #define TSVNAME "neomame32.lst"
 #else
  #ifdef CPSMAME
   #define TSVNAME "cpsmame32.lst"
  #else
   #ifdef TINY_COMPILE
     #define TSVNAME "tinymame32.lst"
   #else
     #define TSVNAME "mame32.lst"
   #endif
  #endif
 #endif
#endif

#define LINEBUF_SIZE  1024
#define NUM_COLUMNS   4

/***************************************************************************
    function prototypes
 ***************************************************************************/

static void TSV_GetPath(char *path);

/***************************************************************************
    Internal variables
 ***************************************************************************/

typedef struct
{
    char *name;
    char *description;
    char *reading;
    char *manufacturer;
} TSV;

static TSV  *tsv_index  = NULL;
static TSV  *tsv_data   = NULL;
static int  need_update = 0;

/***************************************************************************
    External functions
 ***************************************************************************/

void LoadTSV(int games)
{
    char tsvname[_MAX_PATH];
    int  i, j;
    FILE *fp;

    tsv_index = calloc(sizeof(TSV), games + 1);
    if (tsv_index == NULL)
        return;

    tsv_data = calloc(sizeof(TSV), games + 1);
    if (tsv_data == NULL)
    {
        free(tsv_index);
        tsv_index = NULL;
        return;
    }

    TSV_GetPath(tsvname);

    fp = fopen(tsvname, "r");
    if (fp != NULL)
    {
        char *line, *p[NUM_COLUMNS], buf[LINEBUF_SIZE];
        const char *token = "\t\r\n";

        i = 0;
        while (fgets(buf, LINEBUF_SIZE, fp))
        {
            line = buf;
            for (j = 0; j < NUM_COLUMNS; j++)
            {
                p[j] = strtok(line,  token);
                if (p[j] == NULL) break;
                line = NULL;
            }

            tsv_data[i].name         = strdup(p[0]);
            tsv_data[i].description  = strdup(p[1]);
            tsv_data[i].reading      = strdup(p[2]);
            tsv_data[i].manufacturer = strdup(p[3]);

            if (++i > games)
            {
                tsv_data = (TSV *)realloc(tsv_data, (i + 16) * sizeof(TSV));
                games += 16;
            }
        }

        fclose(fp);
    }
    else
        need_update = 1;

    for (i = 0; drivers[i]; i++)
    {
        int index = -1;

        for (j = 0; tsv_data[j].name; j++)
            if (!strcmp(drivers[i]->name, tsv_data[j].name))
                index = j;

        if (index == -1)
        {
            tsv_index[i].name         = (char *)drivers[i]->name;
            tsv_index[i].description  = (char *)drivers[i]->description;
            tsv_index[i].reading      = (char *)drivers[i]->description;
            tsv_index[i].manufacturer = (char *)drivers[i]->manufacturer;
            need_update = 1;
        }
        else
        {
            tsv_index[i].name         = tsv_data[index].name;
            tsv_index[i].description  = tsv_data[index].description;
            tsv_index[i].reading      = tsv_data[index].reading;
            tsv_index[i].manufacturer = tsv_data[index].manufacturer;
        }
    }
}


void SaveTSV(void)
{
    if (need_update)
    {
        char tsvname[_MAX_PATH];
        int  i;
        FILE *fp;
        const char *format = "%s\t%s\t%s\t%s\n";

        TSV_GetPath(tsvname);

        fp = fopen(tsvname, "w");
        if (fp)
        {
            for (i = 0; tsv_index[i].name != NULL; i++)
            {
                fprintf(fp, format,
                        tsv_index[i].name,
                        tsv_index[i].description,
                        tsv_index[i].reading,
                        tsv_index[i].manufacturer);
            }
            fclose(fp);
        }

        free(tsv_index);
        for (i = 0; tsv_data[i].name; i++)
        {
            free(tsv_data[i].name);
            free(tsv_data[i].description);
            free(tsv_data[i].reading);
            free(tsv_data[i].manufacturer);
        }
        free(tsv_data);
    }
}


char *GetDescriptionByIndex(int nIndex)
{
#ifdef JAPANESE
    if (tsv_index && UseJapaneseList())
        return tsv_index[nIndex].description;

    if (UseModifyThe())
        return ModifyThe(drivers[nIndex]->description);
    else
        return (char *)drivers[nIndex]->description;
#else
    if (tsv_index)
        return tsv_index[nIndex].description;
    else
        return ModifyThe(drivers[nIndex]->description);
#endif
}


char *GetDescriptionByName(const char *name)
{
    return GetDescriptionByIndex(GetGameIndex(name));
}


char *GetReadingByIndex(int nIndex)
{
#ifdef JAPANESE
    if (tsv_index && UseJapaneseList())
        return tsv_index[nIndex].reading;

    if (UseModifyThe())
        return ModifyThe(drivers[nIndex]->description);
    else
        return (char *)drivers[nIndex]->description;
#else
    if (tsv_index)
        return tsv_index[nIndex].reading;
    else
        return ModifyThe(drivers[nIndex]->description);
#endif
}


char *GetReadingByName(const char *name)
{
    return GetReadingByIndex(GetGameIndex(name));
}


int GetGameIndex(const char *name)
{
    int i;

    for (i = 0; tsv_index[i].name != NULL; i++)
        if (!strcmp(name, tsv_index[i].name))
            return i;

    return 0;
}


/***************************************************************************
    Internal functions
 ***************************************************************************/

static void TSV_GetPath(char *path)
{
    char drive[_MAX_DRIVE];
    char dir[_MAX_DIR];

    memset(path, 0, sizeof(path));

    GetModuleFileName(NULL, path, _MAX_PATH);

    _splitpath(path, drive, dir, NULL, NULL);

    strcpy(path, drive);
    strcat(path, dir);
    strcat(path, TSVNAME);
}
