/* nodelink example */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <math.h>
#include <vgagames4.h>


int main(int argc, char **argv) {
  struct VG_Hash *hnode;
  struct VG_Nodelink *ndlnk;
  struct VG_Point pnt, *pntp1, *pntp2;
  int len;
  struct VG_Image *imgp;
  struct VG_Position posi;

  (void)argc; (void)argv;

  if (!VG_init("test")) { exit(1); }
  if (!vg4->window->open(VG_WINDOW_SIZE_LOW, VG_WINDOW_SCALE_BEST)) { VG_dest(); exit(1); }
  printf("\n");

  /* +++ create nodes +++ */

  hnode = vg4->hash->create();

  pnt.x = 20; pnt.y = 20;
  vg4->hash->set(hnode, "N1", &pnt, sizeof(pnt));
  imgp = vg4->font->totext("N1", NULL, NULL, NULL, NULL);
  posi.x = pnt.x; posi.y = pnt.y; posi.pos = VG_POS_CENTERED;
  vg4->window->copy(imgp, &posi, NULL);
  vg4->image->destroy(imgp);

  pnt.x = 300; pnt.y = 20;
  vg4->hash->set(hnode, "N2", &pnt, sizeof(pnt));
  imgp = vg4->font->totext("N2", NULL, NULL, NULL, NULL);
  posi.x = pnt.x; posi.y = pnt.y; posi.pos = VG_POS_CENTERED;
  vg4->window->copy(imgp, &posi, NULL);
  vg4->image->destroy(imgp);

  pnt.x = 150; pnt.y = 100;
  vg4->hash->set(hnode, "N3", &pnt, sizeof(pnt));
  imgp = vg4->font->totext("N3", NULL, NULL, NULL, NULL);
  posi.x = pnt.x; posi.y = pnt.y; posi.pos = VG_POS_CENTERED;
  vg4->window->copy(imgp, &posi, NULL);
  vg4->image->destroy(imgp);

  pnt.x = 20; pnt.y = 180;
  vg4->hash->set(hnode, "N4", &pnt, sizeof(pnt));
  imgp = vg4->font->totext("N4", NULL, NULL, NULL, NULL);
  posi.x = pnt.x; posi.y = pnt.y; posi.pos = VG_POS_CENTERED;
  vg4->window->copy(imgp, &posi, NULL);
  vg4->image->destroy(imgp);

  pnt.x = 300; pnt.y = 180;
  vg4->hash->set(hnode, "N5", &pnt, sizeof(pnt));
  imgp = vg4->font->totext("N5", NULL, NULL, NULL, NULL);
  posi.x = pnt.x; posi.y = pnt.y; posi.pos = VG_POS_CENTERED;
  vg4->window->copy(imgp, &posi, NULL);
  vg4->image->destroy(imgp);

  vg4->window->flush();
  printf("Show nodes\n"); fflush(stdout);
  sleep(5);

  /* +++ create links of nodes +++ */

  ndlnk = vg4->nodelink->create();

  /* N1 <-> N2 */
  pntp1 = (struct VG_Point *)vg4->hash->get(hnode, "N1", NULL);
  pntp2 = (struct VG_Point *)vg4->hash->get(hnode, "N2", NULL);
  len = (int)(sqrt(abs(pntp2->x - pntp1->x) * abs(pntp2->x - pntp1->x) + abs(pntp2->y - pntp1->y) * abs(pntp2->y - pntp1->y)) * 10.);
  vg4->nodelink->add(ndlnk, "N1", "N2", len, VG_TRUE);
  vg4->window->draw_line(pntp1->x, pntp1->y, pntp2->x, pntp2->y, VG_COLOR_GREEN);

  /* N1 <-> N3 */
  pntp1 = (struct VG_Point *)vg4->hash->get(hnode, "N1", NULL);
  pntp2 = (struct VG_Point *)vg4->hash->get(hnode, "N3", NULL);
  len = (int)(sqrt(abs(pntp2->x - pntp1->x) * abs(pntp2->x - pntp1->x) + abs(pntp2->y - pntp1->y) * abs(pntp2->y - pntp1->y)) * 10.);
  vg4->nodelink->add(ndlnk, "N1", "N3", len, VG_TRUE);
  vg4->window->draw_line(pntp1->x, pntp1->y, pntp2->x, pntp2->y, VG_COLOR_GREEN);

  /* N2 <-> N3 */
  pntp1 = (struct VG_Point *)vg4->hash->get(hnode, "N2", NULL);
  pntp2 = (struct VG_Point *)vg4->hash->get(hnode, "N3", NULL);
  len = (int)(sqrt(abs(pntp2->x - pntp1->x) * abs(pntp2->x - pntp1->x) + abs(pntp2->y - pntp1->y) * abs(pntp2->y - pntp1->y)) * 10.);
  vg4->nodelink->add(ndlnk, "N2", "N3", len, VG_TRUE);
  vg4->window->draw_line(pntp1->x, pntp1->y, pntp2->x, pntp2->y, VG_COLOR_GREEN);

  /* N2 <-> N5 */
  pntp1 = (struct VG_Point *)vg4->hash->get(hnode, "N2", NULL);
  pntp2 = (struct VG_Point *)vg4->hash->get(hnode, "N5", NULL);
  len = (int)(sqrt(abs(pntp2->x - pntp1->x) * abs(pntp2->x - pntp1->x) + abs(pntp2->y - pntp1->y) * abs(pntp2->y - pntp1->y)) * 10.);
  vg4->nodelink->add(ndlnk, "N2", "N5", len, VG_TRUE);
  vg4->window->draw_line(pntp1->x, pntp1->y, pntp2->x, pntp2->y, VG_COLOR_GREEN);

  /* N5 <-> N3 */
  pntp1 = (struct VG_Point *)vg4->hash->get(hnode, "N5", NULL);
  pntp2 = (struct VG_Point *)vg4->hash->get(hnode, "N3", NULL);
  len = (int)(sqrt(abs(pntp2->x - pntp1->x) * abs(pntp2->x - pntp1->x) + abs(pntp2->y - pntp1->y) * abs(pntp2->y - pntp1->y)) * 10.);
  vg4->nodelink->add(ndlnk, "N5", "N3", len, VG_TRUE);
  vg4->window->draw_line(pntp1->x, pntp1->y, pntp2->x, pntp2->y, VG_COLOR_GREEN);

  /* N5 <-> N4 */
  pntp1 = (struct VG_Point *)vg4->hash->get(hnode, "N5", NULL);
  pntp2 = (struct VG_Point *)vg4->hash->get(hnode, "N4", NULL);
  len = (int)(sqrt(abs(pntp2->x - pntp1->x) * abs(pntp2->x - pntp1->x) + abs(pntp2->y - pntp1->y) * abs(pntp2->y - pntp1->y)) * 10.);
  vg4->nodelink->add(ndlnk, "N5", "N4", len, VG_TRUE);
  vg4->window->draw_line(pntp1->x, pntp1->y, pntp2->x, pntp2->y, VG_COLOR_GREEN);

  vg4->window->flush();
  printf("Show link of nodes\n"); fflush(stdout);
  sleep(5);

  /* +++ walk from N1 to N5 +++ */

  { const char **moveids, *nowid;
    int nmove, i1;

    nmove = vg4->nodelink->moveto(ndlnk, "N1", "N5", &moveids, VG_FALSE);
    if (nmove > 0) {
      nowid = "N1";
      for (i1 = 0; i1 < nmove; i1++) {
        pntp1 = (struct VG_Point *)vg4->hash->get(hnode, nowid, NULL);
        pntp2 = (struct VG_Point *)vg4->hash->get(hnode, moveids[i1], NULL);
        vg4->window->draw_line(pntp1->x, pntp1->y, pntp2->x, pntp2->y, VG_COLOR_YELLOW);
        nowid = moveids[i1];
      }
      free(moveids);
    }
  }

  vg4->window->flush();
  printf("Walk from N1 to N5\n"); fflush(stdout);
  sleep(5);

  /* destroy and exit */
  VG_dest();
  exit(0);
}
