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

void cvtypes_init(struct vgi_canvas_init *);
VG_BOOL cvtypes_readsection(struct vgi_canvas_init *, const struct VG_Canvas *, struct vgi_canvas_item *, char *, const char *);
struct vgi_canvas_item * cvtype_get_item(const struct VG_Canvas *, const char *, int);
struct VG_Rect * cvtypes_get_itag_rect(struct vgi_canvas_init *, const struct VG_Canvas *, const char *, const char *);


enum { CANVAS_TYPE_BUTTON = 0,
       CANVAS_TYPE_SWITCH,
       CANVAS_TYPE_LIST,
       CANVAS_TYPE_CHAIN,
       CANVAS_TYPE_INPUT,
       CANVAS_TYPE_BAR,
       CANVAS_TYPE_MAP,
       CANVAS_TYPE_TEXT,
       CANVAS_TYPE_UNIQKEY,
       CANVAS_TYPE_IMAGE,
       /* FIXME: more types */
       CANVAS_TYPE_MAXENUM  /* last entry */
     };

extern void cvinit_button(struct vgi_canvas_inittype *, int);
extern void cvinit_switch(struct vgi_canvas_inittype *, int);
extern void cvinit_list(struct vgi_canvas_inittype *, int);
extern void cvinit_chain(struct vgi_canvas_inittype *, int);
extern void cvinit_input(struct vgi_canvas_inittype *, int);
extern void cvinit_bar(struct vgi_canvas_inittype *, int);
extern void cvinit_map(struct vgi_canvas_inittype *, int);
extern void cvinit_text(struct vgi_canvas_inittype *, int);
extern void cvinit_uniqkey(struct vgi_canvas_inittype *, int);
extern void cvinit_image(struct vgi_canvas_inittype *, int);
/* FIXME: more types */


/* set cvinit */
void
cvtypes_init(struct vgi_canvas_init *cvinit)
{
  if (cvinit == NULL) { return; }

  cvinit->type = SML3_calloc(CANVAS_TYPE_MAXENUM, sizeof(*cvinit->type));

  cvinit_button(&cvinit->type[CANVAS_TYPE_BUTTON], CANVAS_TYPE_BUTTON);
  cvinit_switch(&cvinit->type[CANVAS_TYPE_SWITCH], CANVAS_TYPE_SWITCH);
  cvinit_list(&cvinit->type[CANVAS_TYPE_LIST], CANVAS_TYPE_LIST);
  cvinit_chain(&cvinit->type[CANVAS_TYPE_CHAIN], CANVAS_TYPE_CHAIN);
  cvinit_input(&cvinit->type[CANVAS_TYPE_INPUT], CANVAS_TYPE_INPUT);
  cvinit_bar(&cvinit->type[CANVAS_TYPE_BAR], CANVAS_TYPE_BAR);
  cvinit_map(&cvinit->type[CANVAS_TYPE_MAP], CANVAS_TYPE_MAP);
  cvinit_text(&cvinit->type[CANVAS_TYPE_TEXT], CANVAS_TYPE_TEXT);
  cvinit_uniqkey(&cvinit->type[CANVAS_TYPE_UNIQKEY], CANVAS_TYPE_UNIQKEY);
  cvinit_image(&cvinit->type[CANVAS_TYPE_IMAGE], CANVAS_TYPE_IMAGE);
  /* FIXME: more types */
} /* Ende cvtypes_init */


/* read section according to its type */
VG_BOOL
cvtypes_readsection(struct vgi_canvas_init *cvinit, const struct VG_Canvas *cvas, struct vgi_canvas_item *cvitem, char *dtptr, const char *sectname)
{
  int type;

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

  type = -1;
  if (strcmp(sectname, "[CV-BUTTON]") == 0) {
    type = CANVAS_TYPE_BUTTON;
  } else if (strcmp(sectname, "[CV-SWITCH]") == 0) {
    type = CANVAS_TYPE_SWITCH;
  } else if (strcmp(sectname, "[CV-LIST]") == 0) {
    type = CANVAS_TYPE_LIST;
  } else if (strcmp(sectname, "[CV-CHAIN]") == 0) {
    type = CANVAS_TYPE_CHAIN;
  } else if (strcmp(sectname, "[CV-INPUT]") == 0) {
    type = CANVAS_TYPE_INPUT;
  } else if (strcmp(sectname, "[CV-BAR]") == 0) {
    type = CANVAS_TYPE_BAR;
  } else if (strcmp(sectname, "[CV-MAP]") == 0) {
    type = CANVAS_TYPE_MAP;
  } else if (strcmp(sectname, "[CV-TEXT]") == 0) {
    type = CANVAS_TYPE_TEXT;
  } else if (strcmp(sectname, "[CV-UNIQKEY]") == 0) {
    type = CANVAS_TYPE_UNIQKEY;
  } else if (strcmp(sectname, "[CV-IMAGE]") == 0) {
    type = CANVAS_TYPE_IMAGE;
  /* FIXME: more types */
  }

  /* call section's read-function to get section's private struct */
  cvitem->vstrct = NULL;
  if (type >= 0) {
    cvitem->type = type;
    if (cvinit->type[type].read_section != NULL) {
      cvitem->vstrct = cvinit->type[type].read_section(cvas, cvitem, dtptr);
    }
  } else {
    pwarn("section \"%s\" unknown\n", sectname);
  }

  if (cvitem->vstrct == NULL) { return VG_FALSE; }

  return VG_TRUE;
} /* Ende cvtypes_readsection */


/* get canvas-item from name and canvas-type, or NULL = not found */
struct vgi_canvas_item *
cvtype_get_item(const struct VG_Canvas *cvas, const char *iname, int type)
{
  struct vgi_canvas_item *cvitem;
  int ielm;

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

  cvitem = NULL;
  
  for (ielm = 0; ielm < cvas->cve.canvas.max; ielm++) {
    if (strcmp(iname, cvas->cve.canvas.e[ielm].name) == 0) {
      if (type < 0 || cvas->cve.canvas.e[ielm].type == type) { break; }
    }
  }

  if (ielm < cvas->cve.canvas.max) { cvitem = &cvas->cve.canvas.e[ielm]; }

  return cvitem;
} /* Ende cvtype_get_item */


/* return hash with tags of text, if available */
struct VG_Rect *
cvtypes_get_itag_rect(struct vgi_canvas_init *cvinit, const struct VG_Canvas *cvas, const char *iname, const char *itag)
{
  struct vgi_canvas_item *cvitem;
  int type;
  struct VG_Rect *prect;

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

  cvitem = cvtype_get_item(cvas, iname, -1);
  if (cvitem == NULL) { return NULL; }

  type = cvitem->type;
  prect = NULL;

  if (cvinit->type[type].get_itag_rect != NULL) {
    prect = cvinit->type[type].get_itag_rect(cvitem, itag);
  }

  return prect;
} /* Ende cvtype_get_itag_rect */
