#include "edbproc.h"
#include "edbpriv.h"	/* private structures */
#include "misc.h"
#include "file.h"
#include "xy.h"
#include "nsc.h"
#include "edb.h"
#include <struct.h>
#include <assert.h>
#include <stdio.h>
#include <ctype.h>
#include <malloc.h>

#define DIAG(x) 

#define FIELDADDR(x,y) ( ((char *) x) + y )

/* find object with short integer keys */
struct genobject *find_object_i(void *self, Empire_Database *edb, struct genobject *rec)
{								
	ObjectDescriptor *this;
	Collection **coll;
	Index **index;
	short key1, key2;
	int slot;						
	this = (ObjectDescriptor *) self;
	coll  = (Collection **) FIELDADDR(edb, this->collection_offset);
	index = (Index **) FIELDADDR(edb, this->index_offset);
	key1 = *((short *) FIELDADDR(rec, this->key1));
	if (this->key2<0)
		key2=0;
	else
		key2 = *((short *) FIELDADDR(rec, this->key2));
	if (!*coll) return NULL; 				
	DIAG( printf("Find %s(%d,%d)\n", this->objdescr, key1, key2); )
	slot=findIndexEntry(*index, key1, key2);		
	if (slot<0) return NULL;				
	return getCollectionItem(*coll, slot);		
}

/* store object with short integer keys */
void store_object_i(void *self, Empire_Database *edb, struct genobject *rec)
{
	ObjectDescriptor *this;
	Collection **coll;
	Index **index;
	short key1, key2;
	int slot;
	this = (ObjectDescriptor *) self;
	coll  = (Collection **) FIELDADDR(edb, this->collection_offset);
	index = (Index **) FIELDADDR(edb, this->index_offset);
	key1 = *((short *) FIELDADDR(rec, this->key1));
	if (this->key2<0)
		key2=0;
	else
		key2 = *((short *) FIELDADDR(rec, this->key2));
	if (!*coll) {
		*coll = newCollection(20,20);
		*index = newIndex(47, 0); /* small prime */
	}
	DIAG( printf("Store %s(%d,%d)\n", this->objdescr, key1, key2); )
	slot=addCollectionItem(*coll, rec);
	setIndexEntry(*index, slot, key1, key2);
}

/* find object with string keys */
struct genobject *find_object_s(void *self, Empire_Database *edb, struct genobject *rec)
{								
	ObjectDescriptor *this;
	Collection **coll;
	Index **index;
	char *key1;
	int slot;						
	this = (ObjectDescriptor *) self;
	coll  = (Collection **) FIELDADDR(edb, this->collection_offset);
	index = (Index **) FIELDADDR(edb, this->index_offset);
	key1 = *((char **) FIELDADDR(rec, this->key1));
	if (!*coll) return NULL; 				
	DIAG( printf("Find %s(%s)\n", this->objdescr, key1); )
	slot=findIndexEntryString(*index, key1);		
	if (slot<0) return NULL;				
	return getCollectionItem(*coll, slot);		
}

/* store object with string keys */
void store_object_s(void *self, Empire_Database *edb, struct genobject *rec)
{
	ObjectDescriptor *this;
	Collection **coll;
	Index **index;
	char *key1;
	int slot;
	this = (ObjectDescriptor *) self;
	coll  = (Collection **) FIELDADDR(edb, this->collection_offset);
	index = (Index **) FIELDADDR(edb, this->index_offset);
	key1 = *((char **) FIELDADDR(rec, this->key1));
	if (!*coll) {
		*coll = newCollection(20,20);
		*index = newIndex(47, 0); /* small prime */
	}
	DIAG( printf("Store %s(%s)\n", this->objdescr, key1); )
	slot=addCollectionItem(*coll, rec);
	setIndexEntryString(*index, slot, key1);
}



extern struct castr sct_cf[], lnd_cf[], shp_cf[], pln_cf[], nuk_cf[], itm_cf[], prd_cf[];
extern struct castr gameinfo_ca[], bmapstr_ca[], cmapstr_ca[], country_ca[];
ObjectDescriptor objTable[] = {
	{ SCT_CLASS, "sctcls", sizeof(struct dchrstr), sct_cf,
		store_object_i, find_object_i,
		fldoff( EDB_Str, sector_build),
		fldoff( EDB_Str, sector_build_index),
		fldoff( dchrstr, d_mnem),
		-1 },
	{ SCT_OBJECT, "sect", sizeof(struct sctstr), sect_ca, 
		store_object_i, find_object_i,
		fldoff( EDB_Str, sector_data),
		fldoff( EDB_Str, sector_data_index),
		fldoff( sctstr, sct_x),
		fldoff( sctstr, sct_y) },
	{ LND_CLASS, "lndcls", sizeof(struct lchrstr), lnd_cf,
		store_object_s, find_object_s,
		fldoff( EDB_Str, land_build),
		fldoff( EDB_Str, land_build_index),
		fldoff( lchrstr, l_name),
		-1 },
	{ LND_OBJECT,"land",  sizeof(struct lndstr), land_ca,
		store_object_i, find_object_i,
		fldoff( EDB_Str, land_data),
                fldoff( EDB_Str, land_data_index),
		fldoff( lndstr, lnd_uid),
		-1 },
	{ SHP_CLASS, "shpcls", sizeof(struct mchrstr), shp_cf,
		store_object_s, find_object_s,
		fldoff( EDB_Str, ship_build),
		fldoff( EDB_Str, ship_build_index),
		fldoff( mchrstr, m_name),
		-1 },
	{ SHP_OBJECT, "ship", sizeof(struct shpstr), ship_ca,
		store_object_i, find_object_i,
		fldoff( EDB_Str, ship_data),
                fldoff( EDB_Str, ship_data_index),
		fldoff( shpstr, shp_uid),
		-1 },
	{ PLN_CLASS,  "plncls", sizeof(struct plchrstr), pln_cf,
		store_object_s, find_object_s,
		fldoff( EDB_Str, plane_build),
		fldoff( EDB_Str, plane_build_index),
		fldoff( plchrstr, pl_name),
		-1 },
	{ PLN_OBJECT, "plane", sizeof(struct plnstr), plane_ca,
		store_object_i, find_object_i,
		fldoff( EDB_Str, plane_data),
                fldoff( EDB_Str, plane_data_index),
		fldoff( plnstr, pln_uid),
		-1 },
	{ NUK_CLASS,  "nukcls", sizeof(struct nchrstr), nuk_cf,
		store_object_s, find_object_s,
		fldoff( EDB_Str, nuke_build),
		fldoff( EDB_Str, nuke_build_index),
		fldoff( nchrstr, n_name),
		-1 },
	{ NUK_OBJECT, "nuke", sizeof(struct nukstr), nuke_ca,
		store_object_i, find_object_i,
		fldoff( EDB_Str, nuke_data),
                fldoff( EDB_Str, nuke_data_index),
		fldoff( nukstr, nuk_uid),
		-1 },
	{ ITM_CLASS,  "itmcls", sizeof(struct ichrstr), itm_cf,
		store_object_i, find_object_i,
		fldoff( EDB_Str, item_class),
		fldoff( EDB_Str, item_class_index),
		fldoff( ichrstr, i_mnem),
		-1 },
	{ PRD_CLASS,  "prdcls", sizeof(struct pchrstr), prd_cf,
		store_object_s, find_object_s,
		fldoff( EDB_Str, product_class),
		fldoff( EDB_Str, product_class_index),
		fldoff( pchrstr, p_sname),
		-1 },
	{ VER_CLASS,  "version", sizeof(struct gameinfo), gameinfo_ca,
		store_object_i, find_object_i,
		fldoff( EDB_Str, game_data),
		fldoff( EDB_Str, game_data_index),
		fldoff( gameinfo, fld_MAXNOC),
		-1 },

	{ BMP_OBJECT,  "bmap", sizeof(struct bmapstr), bmapstr_ca,
		store_object_i, find_object_i,
		fldoff( EDB_Str, bmap_data),
		fldoff( EDB_Str, bmap_data_index),
		fldoff( bmapstr, fld_row),
		-1 },

	{ MAP_OBJECT,  "map", sizeof(struct cmapstr), cmapstr_ca,
		store_object_i, find_object_i,
		fldoff( EDB_Str, map_data),
		fldoff( EDB_Str, map_data_index),
		fldoff( cmapstr, fld_x),
		fldoff( cmapstr, fld_y) },

	{ NAT_OBJECT,  "nation", sizeof(struct country), country_ca,
		store_object_i, find_object_i,
		fldoff( EDB_Str, country_data),
		fldoff( EDB_Str, country_data_index),
		fldoff( country, fld_cnum),
		-1 },

	{ EF_BAD, 0, 0, 0, 0, 0, 0, 0, 0 } };

