/* 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 <dlfcn.h>
#include "iolib.h"

VG_BOOL init_iolib_sdl3(void);
void dest_iolib_sdl3(void);

static int load_symbol(void *, const char *, void **);


/* Funktion aus libSDL3 erhalten */
static int
load_symbol(void *dlib, const char *fct, void **symb)
{
  const char *dlerr;

  if (dlib == NULL || fct == NULL || *fct == '\0' || symb == NULL) {
    outerr("loading SDL3: %s", strerror(EINVAL));
    return 0;
  }

  dlerror();
  *symb = dlsym(dlib, fct);
  if ((dlerr = dlerror()) != NULL) {
    outerr("loading SDL3: unable to resolv %s: %s", fct, dlerr);
    return 0;
  }

  return 1;
} /* Ende load_symbol */


/* init_iolib_sdl3:
 * load and initialize SDL3-library
 * @return  VG_TRUE = OK or VG_FALSE = error
 */
VG_BOOL
init_iolib_sdl3(void)
{
  struct iolib *iolib;
  const char *prefix, *libname;
  char bfile[VGI_PATHSIZE];
  int islocal;

  iolib = SML3_calloc(1, sizeof(*iolib));

  /* SDL3-Bibliothek laden */

#ifndef IOLIB_LOADLIB
# define IOLIB_LOADLIB ""
#endif

  if (*(IOLIB_LOADLIB) == '\0') {
    libname = "libIOlib.so";
  } else {
    libname = strrchr(IOLIB_LOADLIB, '/');
    if (libname != NULL) { libname++; }
  }
  if (libname == NULL || *libname == '\0') {
    outerr("loading SDL3: cannot find library-name of \"%s\"", IOLIB_LOADLIB);
    goto go_error;
  }

  prefix = vg4_get_prefix(&islocal);
  if (islocal) {
    snprintf(bfile, sizeof(bfile), "%s/share/vgagames4/libexec/%s", prefix, libname);
  } else {
    if (*(IOLIB_LOADLIB) == '\0') {
      snprintf(bfile, sizeof(bfile), "%s/share/vgagames4/libexec/%s", prefix, libname);
    } else {
      snprintf(bfile, sizeof(bfile), "%s", (IOLIB_LOADLIB));
    }
  }

  iolib->dlib = dlopen(bfile, RTLD_NOW);
  if (iolib->dlib == NULL) {
    outerr("loading SDL3: dlopen(%s): cannot open file", bfile);
    goto go_error;
  }
  pinfo("loading SDL3: %s\n", bfile);

  /* Funktionen aus Bibliothek erhalten */

#define DEFSYM(ret, fct, parm) \
  do { \
    if (!load_symbol(iolib->dlib, #fct, (void **)(char *)&iolib->syms.fct)) { dlclose(iolib->dlib); goto go_error; } \
  } while (0);
#include "defsyms.h"
#undef DEFSYM

  /* SDL3-Bibliothek initialisieren */
  iolib->syms.SDL_SetAppMetadata(vg4data.gamename, NULL, NULL);
  if (!iolib->syms.SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_EVENTS | SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD)) {
    outerr("loading SDL3: initializing SDL: %s", iolib->syms.SDL_GetError());
    dlclose(iolib->dlib);
    goto go_error;
  }

  /* uebertragen */

  vg4data.iolib.stptr = iolib;

  init_input_sdl3();
  init_window_sdl3();
  init_audio_sdl3();
  init_image_sdl3();
  /* FIXME: weitere Funktionen uebertragen */

  return VG_TRUE;

go_error:
  free(iolib);
  return VG_FALSE;
} /* Ende init_iolib_sdl3 */


/* dest_iolib_sdl3:
 * unload SDL3-library
 */
void
dest_iolib_sdl3(void)
{
  struct iolib *iolib;

  iolib = (struct iolib *)vg4data.iolib.stptr;
  if (iolib == NULL) { return; }

  if (iolib->dlib != NULL) {
    iolib->syms.SDL_Quit();
    dlclose(iolib->dlib);
  }

  free(iolib);
  vg4data.iolib.stptr = NULL;
} /* Ende dest_iolib_sdl3 */
