/* Copyright 2022-2026 Kurt Nienhaus
 *
 * This file is part of VgaGames.
 * VgaGames is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 * VgaGames is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with VgaGames.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include "object.h"

void init_object_instance(void);

static void object_instance_create(struct VG_Object *);
static void object_instance_destroy(unsigned int);
static struct VG_Object * object_instance_getobj(unsigned int);


/* set functions */
void
init_object_instance(void)
{
  vg4->object->instance_create = object_instance_create;
  vg4->object->instance_destroy = object_instance_destroy;
  vg4->object->instance_getobj = object_instance_getobj;
} /* Ende init_object_instance */


/* object_instance_create:
 * set an unused instance-ID into a new created object (.instanceid)
 * @param objp  new created object
 */
static void
object_instance_create(struct VG_Object *objp)
{
  struct vgi_instance *sptr;
  struct SML3_hashelem *he1;
  unsigned int id_start;

  if (objp == NULL) { return; }

  sptr = vg4data.lists.object.i;

  id_start = sptr->id_start;
  for (sptr->id_start++; ; sptr->id_start++) {
    if (sptr->id_start == 0) { continue; }
    if (sptr->id_start == id_start) { outerr("Overflow: no free instance-ID"); abort(); }
    he1 = SML3_hashget(sptr->hiid, (const void *)(size_t)sptr->id_start, 0);
    if (he1 == NULL) { break; }
  }

  he1 = SML3_hashset(sptr->hiid, (const void *)(size_t)sptr->id_start, 0);
  SML3_hashelem_valset(he1, objp, 0);
  objp->instanceid = sptr->id_start;
} /* Ende object_instance_create */


/* object_instance_destroy:
 * destroy an instance-ID for a destroyed object
 * @param instanceid  instance-ID
 */
static void
object_instance_destroy(unsigned int instanceid)
{
  struct vgi_instance *sptr;
  struct SML3_hashelem *he1;

  if (instanceid == 0) { return; }

  sptr = vg4data.lists.object.i;

  he1 = SML3_hashget(sptr->hiid, (const void *)(size_t)instanceid, 0);
  if (he1 != NULL) { SML3_hashdel(he1); }
} /* Ende object_instance_destroy */


/* object_instance_getobj:
 * return the object of an instance-ID
 * @param instanceid  instance-ID
 * @return  object or NULL = not found
 */
static struct VG_Object *
object_instance_getobj(unsigned int instanceid)
{
  struct vgi_instance *sptr;
  struct SML3_hashelem *he1;
  struct VG_Object *objp;

  if (instanceid == 0) { return NULL; }

  sptr = vg4data.lists.object.i;

  he1 = SML3_hashget(sptr->hiid, (const void *)(size_t)instanceid, 0);
  if (he1 == NULL) { return NULL; }

  objp = (struct VG_Object *)SML3_hashelem_valget(he1, NULL);

  return objp;
} /* Ende object_instance_getobj */
