/* object OBJID_BG */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h>
#include "obj-bg.h"

unsigned int objnew_BG(void *);

static void f_free(void *, void *);
static void f_draw(void *, struct VG_Object *);
static int f_data(void *, struct VG_Object *, void *);


/* export-function to create a new object-instance of OBJID_BG
 * @param vgame  private structure of the game
 * @return  instance-ID or 0 = error
 */
unsigned int
objnew_BG(void *vgame)
{
  struct s_game *sgame = (struct s_game *)vgame;
  struct VG_Object *objp;
  struct sobj_bg *objvars;

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

  /* create private struct */

  objvars = calloc(1, sizeof(*objvars));
  if (objvars == NULL) { return 0; }

  /* create background-image */
  { char pfad[512];
    DIR *dirp;
    struct dirent *direntp;
    struct VG_Image *bgimg[16];
    int pfdlen, bgmax, ibg, bgw, bgh, w0, w1, h0, h1;
    struct VG_Position posi;

    bgmax = bgw = bgh = 0;
    snprintf(pfad, sizeof(pfad), "files/images/bg/%d", sgame->svdt.dnew.gamelevel + 1);
    pfdlen = strlen(pfad);
    if ((dirp = opendir(pfad)) == NULL) { fprintf(stderr, "Cannot open \"%s\"\n", pfad); f_free(vgame, objvars); return 0; }
    while ((direntp = readdir(dirp)) != NULL) {
      if (strncmp(direntp->d_name, "bg", 2) == 0) {
        snprintf(pfad + pfdlen, sizeof(pfad) - pfdlen, "/%s", direntp->d_name);
        bgimg[bgmax] = vg4->image->load(pfad);
        if (bgimg[bgmax] == NULL) { f_free(vgame, objvars); return 0; }
        vg4->image->getsize(bgimg[bgmax], NULL, &w1, &h1);
        if (bgw == 0 || bgh == 0) { bgw = w1; bgh = h1; }
        if (w1 != bgw || h1 != bgh) {
          fprintf(stderr, "%s has different size (%d,%d instead of %d,%d)\n", pfad, w1, h1, bgw, bgh);
          f_free(vgame, objvars);
          return 0;
        }
        if (++bgmax == (int)(sizeof(bgimg) / sizeof(*bgimg))) { break; }
      }
    }
    closedir(dirp);
    if (bgmax == 0 || bgw == 0 || bgh == 0) { fprintf(stderr, "Error loading bg?.bmp\n"); f_free(vgame, objvars); return 0; }

    w0 = h0 = BGMUL_SIZE;

    objvars->rect.x = objvars->rect.y = 0;
    objvars->rect.w = sgame->winw / (OBST_SIZE + GANG_SIZE) * (OBST_SIZE + GANG_SIZE)
                        + w0 * (OBST_SIZE + GANG_SIZE) + OBST_SIZE;
    objvars->rect.h = sgame->winh / (OBST_SIZE + GANG_SIZE) * (OBST_SIZE + GANG_SIZE)
                        + h0 * (OBST_SIZE + GANG_SIZE) + OBST_SIZE;

    objvars->imgp = vg4->image->create(objvars->rect.w, objvars->rect.h);
    if (objvars->imgp == NULL) { f_free(vgame, objvars); return 0; } 

    ibg = 0;
    w0 = (objvars->rect.w + OBST_SIZE) / bgw;
    if ((objvars->rect.w + OBST_SIZE) % bgw > 0) { w0++; }
    h0 = (objvars->rect.h + OBST_SIZE) / bgh;
    if ((objvars->rect.h + OBST_SIZE) % bgh > 0) { w0++; }

    for (h1 = 0; h1 < h0; h1++) {
      for (w1 = 0; w1 < w0; w1++) {
        if (bgmax == 2) {
          if (++ibg == 2) { ibg = 0; }
        } else {
          ibg = ZUFALL(OBJID_BG, 0, bgmax - 1);
        }
        posi.pos = VG_POS_UPPER_LEFT;
        posi.x = OBST_SIZE / 2 + w1 * bgw;
        posi.y = OBST_SIZE / 2 + h1 * bgh;
        vg4->image->copy(objvars->imgp, bgimg[ibg], &posi, NULL);
      }
    }

    for (ibg = 0; ibg < bgmax; ibg++) { vg4->image->destroy(bgimg[ibg]); }
  }

  vg4->misc->bgposition_init(objvars->rect.w, objvars->rect.h, 5, 40);

  /* create object-instance */
  objp = vg4->object->create(OBJID_BG, 0, 0, 1, objvars);
  objp->f_free = f_free;
  objp->f_draw = f_draw;
  objp->f_data = f_data;

  return objp->instanceid;
}


/* free private struct of object-instance, called from vg4->object->destroy() */
static void
f_free(void *vgame, void *opriv)
{
  struct sobj_bg *objvars = (struct sobj_bg *)opriv;

  (void)vgame;

  /* free private struct */
  if (objvars->imgp != NULL) { vg4->image->destroy(objvars->imgp); }
  free(objvars);
}


/* draw object-instance, called from vg4->object->call_draw() */
static void
f_draw(void *vgame, struct VG_Object *objp)
{
  struct s_game *sgame = (struct s_game *)vgame;
  struct sobj_bg *objvars = (struct sobj_bg *)objp->opriv;
  struct VG_Rect rect;
  struct VG_Position posi;
  int erg;

  erg = 0;
  if (sgame->instanceid.focus > 0) {
    erg = vg4->object->call_data(sgame, sgame->instanceid.focus, &rect);
  }
  if (erg <= 0) {
    if (vg4->object->call_data(sgame, sgame->instanceid.player, &rect) <= 0) { return; }
  }

  vg4->misc->bgposition_getbg(&rect, &posi, sgame->bg_atonce);
  if (sgame->bg_atonce == VG_TRUE) { sgame->bg_atonce = VG_FALSE; }
  vg4->window->copy(objvars->imgp, &posi, NULL);

#if 0
  { int ix, iy;
    char buf[32];
    struct VG_Image *imgp;
    struct VG_Point *pntp;
    for (ix=1; ix <= sgame->nodes.max_x; ix++) {
      for (iy=1; iy <= sgame->nodes.max_y; iy++) {
        snprintf(buf, sizeof(buf), "%d/%d", ix, iy);
        imgp = vg4->font->totext(buf, NULL, NULL, NULL, NULL);
        pntp = (struct VG_Point *)vg4->hash->get(sgame->nodes.hnode, buf, NULL);
        my_assert(pntp != NULL);
        posi.pos = VG_POS_CENTERED;
        posi.x = pntp->x;
        posi.y = pntp->y;
        posi = vg4->misc->bgposition_getobj(posi);
        vg4->window->copy(imgp, &posi, NULL);
        vg4->image->destroy(imgp);
      }
    }
  }
#endif

}


/* get/set data from/for object-instance, called from vg4->object->call_data() */
static int
f_data(void *vgame, struct VG_Object *objp, void *vptr)
{
  struct s_game *sgame = (struct s_game *)vgame;
  struct sobj_bg *objvars = (struct sobj_bg *)objp->opriv;
  struct VG_Rect *rect = (struct VG_Rect *)vptr;

  if (sgame == NULL || rect == NULL) { return 0; }

  /* return background-rectangle */
  *rect = objvars->rect;

  return 1;
}
