/* canvas-type image
 *   [CV-IMAGE]
 *   name: <arbitrary unique name>
 *   position-itag: (position): <box-tag of an element in the main text>
 *   position-rect: (position): <rectangle (<x>+<w>,<y>+<h>) within the box-tag or the main text>
 *   disable: <whether is disabled: 1 = yes, 0 = no, or missing = enabled>
 *   img: (image file):   [img:]<image file> or txt:<text file> or sprt:<sprite file> or missing
 *   orientation: <left|center|right>
 *   v-orientation: <top|center|bottom>
 *   zoom-in: <whether zoom in too great image fitting into position: 1 = yes, 0 = no, or missing = no>
 *   zoom-out: <whether zoom out too small image fitting into position: 1 = yes, 0 = no, or missing = no>
 */

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

static int type_no = 0;

struct cv_type {
  int orientation;            /* one of VG_ORIENTATIONS */
  int v_orientation;          /* one of VG_ORIENTATIONS */
  struct vgi_imgcnt img;      /* default image, or NULL */
  VG_BOOL zoom_in;            /* whether zooming in if too great */
  VG_BOOL zoom_out;           /* whether zooming out if too small */
};

void cvinit_image(struct vgi_canvas_inittype *, int);

static void * t_read_section(const struct VG_Canvas *, struct vgi_canvas_item *, const char *);
static void t_draw(struct vgi_canvas_data *, struct vgi_canvas_item *, const char **);
static void t_destroy(struct vgi_canvas_item *);
static void t_dump(FILE *, struct vgi_canvas_item *);

static void canvas_image_setimage(struct VG_Canvas *, const char *, struct VG_Image *);
static void canvas_image_setsprite(struct VG_Canvas *, const char *, struct VG_Sprite *);

void
cvinit_image(struct vgi_canvas_inittype *cvinittype, int type)
{
  if (cvinittype == NULL) { return; }

  type_no = type;

  /* cvinit */
  cvinittype->mouse_opaque = VG_FALSE;
  cvinittype->uses_cursor = VG_FALSE;
  cvinittype->read_section = t_read_section;
  cvinittype->get_itag_rect = NULL;
  cvinittype->warp_mouse = NULL;
  cvinittype->pre_exec = NULL;
  cvinittype->draw = t_draw;
  cvinittype->destroy = t_destroy;
  cvinittype->dump = t_dump;

  /* functions */
  vg4->canvas->image_setimage = canvas_image_setimage;
  vg4->canvas->image_setsprite = canvas_image_setsprite;
} /* Ende cvinit_image */


static void *
t_read_section(const struct VG_Canvas *cvas, struct vgi_canvas_item *cvitem, const char *dtptr)
{
  struct SML3_gummi gm1 = SML3_GUM_INITIALIZER;
  struct cv_type *cvtype;
  char bprefix[32], bval[256], *pval;

  if (cvas == NULL || cvitem == NULL || dtptr == NULL) { return NULL; }

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

  if (canvas_get_lineval(dtptr, "img", NULL, 0, bprefix, sizeof(bprefix), bval, sizeof(bval), NULL)) {
    canvas_load_image(cvas, bprefix, bval, &cvtype->img);
  }

  if (canvas_get_lineval(dtptr, "orientation", NULL, 0, NULL, 0, bval, sizeof(bval), NULL)) {
    vg4_intern_str_with_var(&gm1, bval, cvas->cve.hvar, NULL); pval = SML3_gumgetval(&gm1);
    if (strcmp(pval, "left") == 0) {
      cvtype->orientation = VG_ORI_LEFT;
    } else if (strcmp(pval, "center") == 0) {
      cvtype->orientation = VG_ORI_CENTER;
    } else if (strcmp(pval, "right") == 0) {
      cvtype->orientation = VG_ORI_RIGHT;
    } else {
      cvtype->orientation = VG_ORI_CENTER;
    }
  }

  if (canvas_get_lineval(dtptr, "v-orientation", NULL, 0, NULL, 0, bval, sizeof(bval), NULL)) {
    vg4_intern_str_with_var(&gm1, bval, cvas->cve.hvar, NULL); pval = SML3_gumgetval(&gm1);
    if (strcmp(pval, "top") == 0) {
      cvtype->v_orientation = VG_ORI_LEFT;
    } else if (strcmp(pval, "center") == 0) {
      cvtype->v_orientation = VG_ORI_CENTER;
    } else if (strcmp(pval, "bottom") == 0) {
      cvtype->v_orientation = VG_ORI_RIGHT;
    } else {
      cvtype->v_orientation = VG_ORI_CENTER;
    }
  }

  if (canvas_get_lineval(dtptr, "zoom-in", NULL, 0, NULL, 0, bval, sizeof(bval), NULL)) {
    vg4_intern_str_with_var(&gm1, bval, cvas->cve.hvar, NULL); pval = SML3_gumgetval(&gm1);
    DETECT_BOOLEAN(pval, cvtype->zoom_in);
  }

  if (canvas_get_lineval(dtptr, "zoom-out", NULL, 0, NULL, 0, bval, sizeof(bval), NULL)) {
    vg4_intern_str_with_var(&gm1, bval, cvas->cve.hvar, NULL); pval = SML3_gumgetval(&gm1);
    DETECT_BOOLEAN(pval, cvtype->zoom_out);
  }

  SML3_gumdest(&gm1);

  cvitem->isselectable = VG_FALSE;

  return cvtype;
} /* Ende t_read_section */


static void
t_draw(struct vgi_canvas_data *cvdata, struct vgi_canvas_item *cvitem, const char **selname)
{
  struct cv_type *cvtype;

  if (cvdata == NULL || cvdata->cvas == NULL || cvitem == NULL || selname == NULL) { return; }
  if (cvitem->rimg == NULL) { return; }
  cvtype = (struct cv_type *)cvitem->vstrct;
  if (cvtype == NULL) { return; }

  /* draw */
  { struct VG_Image *imgp;
    struct VG_ImagecopyAttr iattr;
    struct VG_Position posb;

    imgp = vg4_intern_get_img_from_imgcnt(&cvtype->img, &iattr);
    if (cvitem->isdisabled) {  /* disabled */
      iattr.pixel.pixelcolor = VG_PIXELCOLOR_GREY;
      iattr.pixel.brightness = iattr.pixel.brightness * 4 / 5;
    }

    /* draw out */
    if (imgp != NULL) {
      int imgw, imgh;
      vg4->image->clear(cvitem->rimg);
      vg4->image->getsize(imgp, NULL, &imgw, &imgh);
      if (cvtype->zoom_in) {
        int przw = 100, przh = 100, prz;
        if (imgw > cvitem->rect.w) {
          przw = cvitem->rect.w * 100 / (imgw == 0 ? 1 : imgw);
        }
        if (imgh > cvitem->rect.h) {
          przh = cvitem->rect.h * 100 / (imgh == 0 ? 1 : imgh);
        }
        prz = (przw < przh ? przw : przh);
        if (prz < 100) {
          iattr.image.zoom_width = iattr.image.zoom_height = prz;
          iattr.image.zoom_ispercent = VG_TRUE;
        }
      }
      if (cvtype->zoom_out) {
        int przw = 100, przh = 100, prz;
        if (cvitem->rect.w > imgw) {
          przw = cvitem->rect.w * 100 / (imgw == 0 ? 1 : imgw);
        }
        if (cvitem->rect.h > imgh) {
          przh = cvitem->rect.h * 100 / (imgh == 0 ? 1 : imgh);
        }
        prz = (przw < przh ? przw : przh);
        if (prz > 100) {
          iattr.image.zoom_width = iattr.image.zoom_height = prz;
          iattr.image.zoom_ispercent = VG_TRUE;
        }
      }
      posb = canvas_set_posi(&cvitem->rect, imgp, &iattr.image, cvtype->orientation, cvtype->v_orientation);
      vg4->image->copy(cvitem->rimg, imgp, &posb, &iattr);
      posb.pos = VG_POS_UPPER_LEFT;
      posb.x = cvdata->xadd + cvitem->rect.x;
      posb.y = cvdata->yadd + cvitem->rect.y;
      vg4->window->copy(cvitem->rimg, &posb, NULL);
    }
  }
} /* Ende t_draw */


static void
t_destroy(struct vgi_canvas_item *cvitem)
{
  struct cv_type *cvtype;

  if (cvitem == NULL) { return; }
  cvtype = (struct cv_type *)cvitem->vstrct;
  if (cvtype == NULL) { return; }

  vg4_intern_free_imgcnt(&cvtype->img);

  free(cvtype);
} /* Ende t_destroy */


static void
t_dump(FILE *outfp, struct vgi_canvas_item *cvitem)
{
  struct cv_type *cvtype;
  const char *namptr;

  if (outfp == NULL || cvitem == NULL) { return; }
  cvtype = (struct cv_type *)cvitem->vstrct;
  if (cvtype == NULL) { return; }

  fprintf(outfp, "    type=image\n");
  namptr = vg4_intern_get_name_from_imgcnt(&cvtype->img);
  fprintf(outfp, "    img=%s\n", namptr);
} /* Ende t_dump */


/* canvas_image_setimage:
 * set image
 * @param cvas   canvas
 * @param iname  name of image-item
 * @param imgp   image (taken be reference, so don't free it afterwards), or NULL = no image
 */
static void
canvas_image_setimage(struct VG_Canvas *cvas, const char *iname, struct VG_Image *imgp)
{
  struct vgi_canvas_item *cvitem;
  struct cv_type *cvtype;

  if (cvas == NULL || iname == NULL || *iname == '\0') { return; }

  cvitem = cvtype_get_item(cvas, iname, type_no);
  if (cvitem == NULL) { return; }
  cvtype = (struct cv_type *)cvitem->vstrct;
  if (cvtype == NULL) { return; }

  vg4_intern_free_imgcnt(&cvtype->img);
  if (imgp != NULL) {
    cvtype->img.type = VGI_IMGCNT_IMAGE;
    cvtype->img.u.img = imgp;
  }
} /* Ende canvas_image_setimage */


/* canvas_image_setsprite:
 * set sprite
 * @param cvas   canvas
 * @param iname  name of image-item
 * @param sprt   sprite (taken be reference, so don't free it afterwards), or NULL = no sprite
 */
static void
canvas_image_setsprite(struct VG_Canvas *cvas, const char *iname, struct VG_Sprite *sprt)
{
  struct vgi_canvas_item *cvitem;
  struct cv_type *cvtype;

  if (cvas == NULL || iname == NULL || *iname == '\0') { return; }

  cvitem = cvtype_get_item(cvas, iname, type_no);
  if (cvitem == NULL) { return; }
  cvtype = (struct cv_type *)cvitem->vstrct;
  if (cvtype == NULL) { return; }

  vg4_intern_free_imgcnt(&cvtype->img);
  if (sprt != NULL) {
    cvtype->img.type = VGI_IMGCNT_SPRITE;
    cvtype->img.u.sprt = sprt;
  }
} /* Ende canvas_image_setsprite */
