/*
 * pqtrain.c --
 *       Demonstration of the C version of Libpq, the POSTGRES frontend
 *       library.  Calls X10R4 library routines.  Throws up a window
 *       and plots a hypothetical rail network (nodes and lines).  Then
 *       runs a train along a path of the network.  Retrieves tuples from
 *       two relations -- "nodes" and "lines" from a database "mtrain".  
 *       Could be modified to use POSTGRES point and line ADT's.
 *       See the README file in this directory for setup information.
 *       See the POSTGRES Reference Manual for explanations of libpq commands.
 */
#include <stdio.h>
#include <X/Xlib.h>
#include <math.h>
#include "pqtrain.h"
#include "libpq.h"
#include "pqtrain.bitmap"


Window w;
POINT  table[100];		/* Holds x and y coords for a point */
Pixmap train_pixmap;

pq_init_main()
{
	
	if (XOpenDisplay("") == NULL)
	{
		printf("X_OpenWindow; couldn't open the display\n");
		exit(1);
        }
    	w = XCreateWindow(RootWindow,INITIAL_XCOORD,
			  INITIAL_YCOORD,INITIAL_WIDTH, INITIAL_HEIGHT,
			  2,BlackPixmap,WhitePixmap);
        XMapWindow(w);
    	XFlush();
}

Pixmap 
pq_create_pixmap(w,h,bits)
int w,h;
short bits[];
{
  Bitmap ib;

  ib=XStoreBitmap(w,h,bits);
  return(XMakePixmap(ib,BlackPixel,WhitePixel));
}

void
pq_draw_line(points)
LINE   *points;
{
	Vertex line[2];

	line[0].x = points->begpt.x;
	line[0].y = points->begpt.y;
	line[1].x = points->endpt.x;
	line[1].y = points->endpt.y;
	XDraw(w, line, 2, 1, 1, BlackPixel, GXcopy, AllPlanes);
	XFlush();
}
	
void
pq_draw_pt(point)
POINT *point;

{
	XPixSet(w, point->x, point->y, 3, 3, BlackPixel);
	XFlush();
}
	
void 
pq_draw_pixmap(coords)
POINT *coords;
{
	int xcoord,ycoord;

	xcoord = coords->x - train_height/2;
	ycoord = coords->y - train_width/2;
	XPixmapPut(w,0,0,xcoord,ycoord, train_width,
		   train_height,train_pixmap,GXxor,AllPlanes);
	XFlush();
}

void
pq_init_train()
{
	train_pixmap =
	  pq_create_pixmap(train_width,train_height,train_bits);
}
#define sqr(x) ((x)*(x))

void calc_next_move(train_x, train_y, dest_x, dest_y, dist, new_x, new_y)
float train_x, train_y, dest_x, dest_y, dist;
float *new_x, *new_y;
{
    float ratio, distance;
    
    distance = sqrt(sqr(train_x - dest_x)
		    + sqr(train_y - dest_y));
    if (dist > distance)
	  {
	      *new_x = dest_x;
	      *new_y = dest_y;
	      return;
	  }
    ratio = distance / dist;
    *new_x = (((ratio - 1.0) * train_x) + dest_x) / ratio;
    *new_y = (((ratio - 1.0) * train_y) + dest_y) / ratio;
    
}

void run_train(from_indx,to_indx)
int from_indx,to_indx;
{
        POINT point;
	float train_x, train_y, distance;
	int i;
	
	train_x = table[from_indx].x;
	train_y = table[from_indx].y;
	distance = sqrt((float)sqr(table[from_indx].x - table[to_indx].x) +
			(float)sqr(table[from_indx].y - table[to_indx].y));    
	
	for (i=0;i<6;i++)
	  {
		  if (i>0)
		    pq_draw_pixmap(&point);
		  calc_next_move((float)train_x,
			 (float)train_y, (float)table[to_indx].x,
			 (float)table[to_indx].y,
			 (distance / 6.0), &train_x, &train_y);
		  point.x=train_x;
		  point.y=train_y;
		  pq_draw_pixmap(&point);
		  usleep(200000);
	  }
	pq_draw_pixmap(&point);
}

main ()
{
    int i, value;
    POINT point;
    LINE line;

    int j, k, g, n, m;
    PortalBuffer *p;
    char *str;

    
    pq_init_main();
    pq_init_train();

    /* Specify the database to access. */
    PQsetdb ("mtrain");

    PQexec ("retrieve portal nportal (nodes.all)");
    PQexec ("fetch all in nportal");

    /*          Examine all the tuples fetched.        */

    p = PQparray ("nportal");
    g = PQngroups (p);
    n = PQntuplesGroup (p, 0);
    m = PQnfields (p, 0);

    for (i=0; i<n; i++) {
	str = PQgetvalue(p, i, 0);
	value = atoi(str);
	point.x = table[value].x = atoi(PQgetvalue(p, i, 1));
	point.y = table[value].y = atoi(PQgetvalue(p, i, 2));
	pq_draw_pt(&point);
    }

    
    PQexec ("retrieve portal lportal (lines.all)");
    PQexec ("fetch all in lportal");

    p = PQparray ("lportal");
    g = PQngroups (p);
    n = PQntuplesGroup (p, 0);
    m = PQnfields (p, 0);

    for (i=0; i<n; i++) {
	value = atoi(PQgetvalue(p, i, 1));
        line.begpt.x = table[value].x;
	line.begpt.y = table[value].y;
	value = atoi(PQgetvalue(p, i, 2));
	line.endpt.x = table[value].x;
	line.endpt.y = table[value].y;

      pq_draw_line(&line);
    }
    /* Move train from point 11 to point 3  -- note it would be nicer
       to use the PATH adt to store the path
     */
    
    run_train(11,14);
    run_train(14,15);
    run_train(15,16);
    run_train(16,17);
    run_train(17,3);

    PQfinish();

}
    
