/* canvas-type percent-bar
 *   [CV-BAR]
 *   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>
 *   percent-dfl: <default percent-value, or missing = 0>
 *   img-bar: <image file for bar, width corresponds to 100%>
 *   img-bar-overdrive: <overdrive-percent-value>:[<image file for bar, width corresponds to 100%>]
 */

#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 percent;               /* percent-value */
  int repw;                  /* waiting value before repeating */
  struct VG_Image *img_bar;  /* bar image */
  struct {                   /* overdrive */
    int percent;               /* overdrive percent, or 0 = no overdrive */
    struct VG_Image *img_bar;  /* overdrive bar image */
  } ovd;
};

void cvinit_bar(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_bar_set_percent(struct VG_Canvas *, const char *, int);
static int canvas_bar_get_percent(struct VG_Canvas *, const char *);


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

  type_no = type;

  /* cvinit */
  cvinittype->mouse_opaque = VG_FALSE;
  cvinittype->uses_cursor = VG_TRUE;
  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->bar_set_percent = canvas_bar_set_percent;
  vg4->canvas->bar_get_percent = canvas_bar_get_percent;
} /* Ende cvinit_bar */


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 bval[256], *pval;

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

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

  if (canvas_get_lineval(dtptr, "percent-dfl", NULL, 0, NULL, 0, bval, sizeof(bval), NULL)) {
    vg4_intern_str_with_var(&gm1, bval, cvas->cve.hvar, NULL); pval = SML3_gumgetval(&gm1);
    cvtype->percent = atoi(pval);
    if (cvtype->percent < 0) { cvtype->percent = 0; }
    if (cvtype->percent > 100) { cvtype->percent = 100; }
  }

  if (canvas_get_lineval(dtptr, "img-bar", NULL, 0, NULL, 0, bval, sizeof(bval), NULL)) {
    char rfile[VGI_PATHSIZE];
    if (*bval != '/') {
      vg4->misc->strccat(rfile, sizeof(rfile), cvas->cve.dirname, "/", bval, NULL);
    } else {
      vg4->misc->strcpy(rfile, sizeof(rfile), bval + 1);
    }
    vg4_intern_fpath_with_var(rfile, sizeof(rfile), cvas->cve.hvar);
    cvtype->img_bar = vg4_image_load_nolist(rfile);
  }

  if (canvas_get_lineval(dtptr, "img-bar-overdrive", NULL, 0, NULL, 0, bval, sizeof(bval), NULL)) {
    char rfile[VGI_PATHSIZE], *pt1;
    if ((pt1 = strchr(bval, ':')) != NULL) {
      *pt1++ = '\0';
      vg4_intern_str_with_var(&gm1, bval, cvas->cve.hvar, NULL); pval = SML3_gumgetval(&gm1);
      cvtype->ovd.percent = atoi(pval);
      if (cvtype->ovd.percent > 0 && cvtype->ovd.percent < 100) {
        if (*pt1 != '\0') {
          if (*pt1 != '/') {
            vg4->misc->strccat(rfile, sizeof(rfile), cvas->cve.dirname, "/", pt1, NULL);
          } else {
            vg4->misc->strcpy(rfile, sizeof(rfile), pt1 + 1);
          }
          vg4_intern_fpath_with_var(rfile, sizeof(rfile), cvas->cve.hvar);
          cvtype->ovd.img_bar = vg4_image_load_nolist(rfile);
        }
      } else {
        cvtype->ovd.percent = 0;
      }
    }
  }

  SML3_gumdest(&gm1);

  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;
  int leftright;

  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; }

  /* check if shall moving left (-1) or right (1) */
  leftright = 0;
  if (cvdata->hasfocus) {  /* has focus */
    if (VGI_CVKEY_NEWPRESSED(cvdata->keys.k[CV_KEY_LEFT]) || VGI_CVKEY_NEWPRESSED(cvdata->keys.k[CV_KEY_DOWN])) {
      leftright = -1;
      cvtype->repw = VGI_CANVAS_REPWMAX;
    }
    if (VGI_CVKEY_PRESSED(cvdata->keys.k[CV_KEY_LEFT]) || VGI_CVKEY_PRESSED(cvdata->keys.k[CV_KEY_DOWN])) {
      if (cvtype->repw > 0) { cvtype->repw--; } else { leftright = -1; }
    }

    if (VGI_CVKEY_NEWPRESSED(cvdata->keys.k[CV_KEY_RIGHT]) || VGI_CVKEY_NEWPRESSED(cvdata->keys.k[CV_KEY_UP])) {
      leftright = 1;
      cvtype->repw = VGI_CANVAS_REPWMAX;
    }
    if (VGI_CVKEY_PRESSED(cvdata->keys.k[CV_KEY_RIGHT]) || VGI_CVKEY_PRESSED(cvdata->keys.k[CV_KEY_UP])) {
      if (cvtype->repw > 0) { cvtype->repw--; } else { leftright = 1; }
    }
  }

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

    if (cvtype->img_bar == NULL) {
      cvtype->img_bar = vg4_image_create_nolist(cvitem->rect.w, cvitem->rect.h);
      vg4->image->fill(cvtype->img_bar, VG_COLOR_WHITE);
    }

    if (cvtype->ovd.percent > 0 && cvtype->ovd.img_bar == NULL) {
      cvtype->ovd.img_bar = vg4_image_create_nolist(cvitem->rect.w, cvitem->rect.h);
      vg4->image->fill(cvtype->ovd.img_bar, VG_COLOR_RED);
    }

    imgp = cvtype->img_bar;
    VG_IMAGECOPY_ATTR_DEFAULT(&iattr);

    if (cvitem->rect.w >= cvitem->rect.h) {
      updown = VG_FALSE;
    } else {
      updown = VG_TRUE;
    }

    if (cvdata->hasfocus) {  /* has focus */
      /* change bar-item according to keypress left and right */
      if (leftright < 0) {  /* left */
        cvtype->percent--;
        if (cvtype->percent < 0) { cvtype->percent = 0; }
      } else if (leftright > 0) {  /* right */
        cvtype->percent++;
        if (cvtype->percent > 100) { cvtype->percent = 100; }
      }

      /* change bar-item according to mouse */
      if (cvdata->cvas->cve.mouse.show) {
        if (VGI_CVKEY_PRESSED(cvdata->keys.m_left)) {
          int xm, ym, sizewh;
          if (vg4->input->mouse_position(&xm, &ym)) {
            if (updown) {
              ym = ym - cvdata->yadd - cvitem->rect.y;
              sizewh = cvitem->rect.h - 1;
              if (sizewh < 1) { sizewh = 1; }
              cvtype->percent = 100 - ym * 100 / sizewh;
            } else {
              xm = xm - cvdata->xadd - cvitem->rect.x;
              sizewh = cvitem->rect.w - 1;
              if (sizewh < 1) { sizewh = 1; }
              cvtype->percent = xm * 100 / sizewh;
            }
            if (cvtype->percent > 100) { cvtype->percent = 100; }
            if (cvtype->percent < 0) { cvtype->percent = 0; }
          }
        }
      }

      /* done? */
      if (VGI_CVKEY_NEWPRESSED(cvdata->keys.k[CV_KEY_RETURN])) {
        *selname = cvitem->name;
      }

    } else if (cvitem->isdisabled) {  /* disabled */
      iattr.pixel.pixelcolor = VG_PIXELCOLOR_GREY;
      iattr.pixel.brightness = iattr.pixel.brightness * 4 / 5;
    }

    /* overdrive? */
    if (cvtype->ovd.percent > 0 && cvtype->percent >= cvtype->ovd.percent) {
      imgp = cvtype->ovd.img_bar;
    }

    /* draw out */
    vg4->image->clear(cvitem->rimg);
    if (updown) {
      posb.pos = VG_POS_UPPER_LEFT;
      posb.x = 0;
      posb.y = cvitem->rect.h - cvtype->percent * cvitem->rect.h / 100;
    } else {
      posb.pos = VG_POS_UPPER_RIGHT;
      posb.x = cvtype->percent * cvitem->rect.w / 100 - 1;
      posb.y = 0;
    }
    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);
    if (cvdata->hasfocus) {  /* has focus */
      canvas_draw_actborder(&cvitem->rect, cvdata->xadd, cvdata->yadd);
    }
  }
} /* 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; }

  if (cvtype->img_bar != NULL) { vg4->image->destroy(cvtype->img_bar); }
  if (cvtype->ovd.img_bar != NULL) { vg4->image->destroy(cvtype->ovd.img_bar); }

  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=percent-bar\n");
  fprintf(outfp, "    percent=%d\n", cvtype->percent);
  namptr = vg4->image->getname(cvtype->img_bar);
  fprintf(outfp, "    img-bar=%s\n", namptr);
  fprintf(outfp, "    overdrive-percent=%d\n", cvtype->ovd.percent);
  namptr = vg4->image->getname(cvtype->ovd.img_bar);
  fprintf(outfp, "    img-bar-overdrive=%s\n", namptr);
} /* Ende t_dump */


/* canvas_bar_set_percent:
 * set percent of a percent-bar
 * @param cvas     canvas
 * @param iname    name of percent-bar
 * @param percent  percent value
 */
static void
canvas_bar_set_percent(struct VG_Canvas *cvas, const char *iname, int percent)
{ 
  struct vgi_canvas_item *cvitem;
  struct cv_type *cvtype;
  
  if (cvas == NULL || iname == NULL || *iname == '\0') { return; }
  if (percent < 0) { percent = 0; }
  if (percent > 100) { percent = 100; }

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

  cvtype->percent = percent;
} /* Ende canvas_bar_set_percent */


/* canvas_bar_get_percent:
 * get percent value of a percent-bar
 * @param cvas     canvas
 * @param iname    name of percent-bar
 * @return  percent value
 */
static int
canvas_bar_get_percent(struct VG_Canvas *cvas, const char *iname)
{
  struct vgi_canvas_item *cvitem;
  struct cv_type *cvtype;
  
  if (cvas == NULL || iname == NULL || *iname == '\0') { return 0; }

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

  return cvtype->percent;
} /* Ende canvas_bar_get_percent */
