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

	tsv.c

	function for dealing with TSV file.  

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

#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 "misc.h"
#include "tsv.h"
#ifdef WINUI
#include "ui/options.h"
#include "ui/Win32ui.h"
#endif

#define TSVNAME "japanese.lst"
#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;

#ifndef JAPANESE
	return;
#endif

	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 nIndex = -1;

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

		if (nIndex == -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[nIndex].name;
			tsv_index[i].description  = tsv_data[nIndex].description;
			tsv_index[i].reading	  = tsv_data[nIndex].reading;
			tsv_index[i].manufacturer = tsv_data[nIndex].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, int bUse)
{
#ifdef JAPANESE
	if (tsv_index && bUse)
		return tsv_index[nIndex].description;
#endif
		return ModifyThe(drivers[nIndex]->description);
}


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


char *GetReadingByIndex(int nIndex, int bUse)
{
#ifdef JAPANESE
	if (tsv_index && bUse)
		return tsv_index[nIndex].reading;
#endif
		return ModifyThe(drivers[nIndex]->description);
}


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


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);
}
