/*
 * draw_route.c
 * Copyright (C) Steffen Pohle 2011 <steffen@gulpe.de>
 * 
 * main.c is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * main.c is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU  General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <sys/time.h>
#include <math.h>

#include "osmroute.h"
#include "draw.h"
#include "map.h"
#include "routing.h"
#include "gps.h"
#include "system.h"


void draw_routelist (struct rtwaylist *rtlist, struct line_style linestyle, int cnt);



/****************************************************************************
 * drawing routing information on the screen
 */
void draw_gui_route () {
	struct map_hash *mh;
	struct map_way *mw;
	struct line_style tmplinestyle;
	iPoint p1, p2, center = {gfx_screensize.x/2, gfx_screensize.y/2};
	fPoint nd;
	float angle, f;
	int j, n, i;
	char text[256];
	struct rtwaylist *rtlist = NULL;

	if (route == NULL) return;

	/*
	 * draw the destination route thick
	 */
	mh = map_hash_get (route->dest.lon, route->dest.lat, MHLOAD_RELOAD);
	mw = map_way_find (mh, route->dest_way_id, route->dest_way_sid);
	if (mw) {
		/* go through all the nodes */
		tmplinestyle.width = 5;
		tmplinestyle.c = color[COLOR_white][3];
		for (n = 0; n < mw->p_cnt; n++) {
			p2 = p1;
			nd.x = map_lon2km (view_lon - mw->p[n].lon, mw->p[n].lat);
			nd.y = map_lat2km (view_lat - mw->p[n].lat);
			p1.x = center.x - (nd.x / view_scale);
			p1.y = center.y + (nd.y / view_scale);
			if (n > 0) {
				draw_lineway (NULL, p1.x, p1.y, p2.x, p2.y, tmplinestyle);
			}
		}
	}	
	
	/* 
	 * draw the destination cross
	 */
	tmplinestyle.width = 2.0;
	tmplinestyle.c = tmplinestyle.borderc = color[COLOR_greengray][3];

	p1 = draw_geo2screen (view_lon, view_lat, route->dest.lon, route->dest.lat);
	p1.x += center.x;
	p1.y += center.y;

	draw_line (NULL, p1.x-5, p1.y-5, p1.x+5, p1.y+5, tmplinestyle);
	draw_line (NULL, p1.x+5, p1.y-5, p1.x-5, p1.y+5, tmplinestyle);

	if (view_flags & DRAW_DEBUG && route->state > ROUTING_INIT) {
		p1 = draw_geo2screen (view_lon, view_lat, route->pos.lon, route->pos.lat);
		p1.x += center.x;
		p1.y += center.y;
		p2 = draw_geo2screen (view_lon, view_lat, route->dest.lon, route->dest.lat);
		p2.x += center.x;
		p2.y += center.y;
		draw_line (NULL, p1.x, p1.y, p2.x, p2.y, tmplinestyle);
	}
	
	/*
	 * display some information
	 */
	if (route->state == ROUTING_CALC) {
		sprintf (text, _("calculating: %5.2g%% %g/%g"), 100.0-(100.0*route->closest_distance/route->distance), route->closest_distance, route->distance);
	}
	else if (route->state == ROUTING_OPTIMIZE) {
		sprintf (text, _("optimizing:"));
	}
	else if (route->state == ROUTING_ONWAY) {
		sprintf (text, _("onway dist: %3.1fkm"), route->distance);
	}
	else if (route->state == ROUTING_INIT) {
		sprintf (text, _("init"));
	}
	else if (route->state == ROUTING_ABORT) {
		sprintf (text, _("abort"));
	}
	else {
		sprintf (text, _("unknown state: %d"), route->state);
	}
	gfx_draw_text (NULL, 0, gfx_screensize.y-32, text, &color[COLOR_greengray][3]);

	/* 
	 * draw compass 
	 */
	tmplinestyle.width = 1.0;
	tmplinestyle.c = tmplinestyle.borderc = color[COLOR_white][3];
	draw_line (NULL, center.x-100, 40, center.x+100, 40, tmplinestyle);
	for (angle = 0.0; angle < 360.0; angle = angle + 45.0) {
		f = angle - drawgps_data.direction;
		if (f > 180.0) f = f - 360.0;
		if (f < -180.0) f = f + 360.0;
		if (f >= -100.0 && f <= 100.0) {
			draw_line (NULL, center.x+f, 40, center.x+f, 37, tmplinestyle);
			if (angle == 0.0) { 
				sprintf (text, _("N"));
				gfx_draw_text (NULL, center.x+f-4, 41, text, &color[COLOR_white][3]);
			}
			else if (angle == 90.0) { 
				sprintf (text, _("E"));
				gfx_draw_text (NULL, center.x+f-4, 41, text, &color[COLOR_white][3]);
			}
			else if (angle == 180.0) { 
				sprintf (text, _("S"));
				gfx_draw_text (NULL, center.x+f-4, 41, text, &color[COLOR_white][3]);
			}
			else if (angle == 270.0) { 
				sprintf (text, _("W"));
				gfx_draw_text (NULL, center.x+f-4, 41, text, &color[COLOR_white][3]);
			}
		}
	}

	f = route->angle - drawgps_data.direction;
	if (f > 180.0) f = f - 360.0;
	if (f < -180.0) f = f + 360.0;
			
	if (f < -100.0) f = -100.0;
	else if (f > 100.0) f = 100.0;
	else {
		tmplinestyle.width = 2.0;
		tmplinestyle.c = tmplinestyle.borderc = color[COLOR_greengray][3];
		draw_line (NULL, center.x+f, 45, center.x+f, 35, tmplinestyle);
		gfx_draw_text (NULL, center.x+f-4, 41, "*", &color[COLOR_greengray][3]);
	}

	
	/*
	 * debug information 
	 */
	if (view_flags & DRAW_DEBUG) {
		for (j = 0; j < 4; j++) {
			if (j == 0) {
				rtlist = &route->stack1;
				tmplinestyle.width = 2;
				tmplinestyle.c = color[COLOR_blue][3];
				draw_routelist (rtlist, tmplinestyle, 64);
			}
			else if (j == 1) {
				rtlist = &route->stack2;
				tmplinestyle.width = 2;
				tmplinestyle.c = color[COLOR_blue][3];
				draw_routelist (rtlist, tmplinestyle, 64);
			} 
			else if (j == 2) {
				rtlist = &route->stack3;
				tmplinestyle.width = 2;
				tmplinestyle.c = color[COLOR_blue][3];
				draw_routelist (rtlist, tmplinestyle, 64);
			} 
			else if (j == 3) {
				rtlist = &route->ways;
				tmplinestyle.width = 3;
				tmplinestyle.c = color[COLOR_red][2];
				draw_routelist (rtlist, tmplinestyle, -1);
			} 
		}

		/*
		 * draw information about the way
		 */
		rtlist = NULL;
		/* check route->ways */
		for (i = 0; i < route->ways.cnt; i++) {
			if (mouse_over_way_id == route->ways.array[i].way.id && mouse_over_way_sid == route->ways.array[i].way.sid) {
				rtlist = &route->ways;
				break;
			}
		}
		/* check route->stacks */
		if (rtlist == NULL) for (i = 0; i < route->stack1.cnt; i++) {
			if (mouse_over_way_id == route->stack1.array[i].way.id && mouse_over_way_sid == route->stack1.array[i].way.sid) {
				rtlist = &route->stack1;
				break;
			}
		}
		if (rtlist == NULL) for (i = 0; i < route->stack2.cnt; i++) {
			if (mouse_over_way_id == route->stack2.array[i].way.id && mouse_over_way_sid == route->stack2.array[i].way.sid) {
				rtlist = &route->stack2;
				break;
			}
		}
		if (rtlist == NULL) for (i = 0; i < route->stack3.cnt; i++) {
			if (mouse_over_way_id == route->stack3.array[i].way.id && mouse_over_way_sid == route->stack3.array[i].way.sid) {
				rtlist = &route->stack3;
				break;
			}
		}

		if (rtlist && i >= 0) {
			sprintf (text, "dist2pos:%g dist2dest:%g step:%d", rtlist->array[i].dist2pos, rtlist->array[i].dist2dest, rtlist->array[i].step);
			gfx_draw_text (NULL, 200, gfx_screensize.y-16, text, &color[COLOR_yellow][3]);
			sprintf (text, "prio:%g deltadistr:%g", rtlist->array[i].priority, rtlist->array[i].deltadist);
			gfx_draw_text (NULL, 200, gfx_screensize.y-28, text, &color[COLOR_yellow][3]);
			sprintf (text, "%lld:%d (pnr:%d)", rtlist->array[i].way.id, rtlist->array[i].way.sid, rtlist->array[i].pnr);
			gfx_draw_text (NULL, 200, gfx_screensize.y-40, text, &color[COLOR_yellow][3]);
			sprintf (text, "way:%g cycle:%d:%d", rtlist->array[i].dist2dest, rtlist->array[i].cycle1, rtlist->array[i].cycle2);
			gfx_draw_text (NULL, 200, gfx_screensize.y-52, text, &color[COLOR_yellow][3]);
		}

		/* display additional information */
		sprintf (text, "r->stack1: %d prio:%g", route->stack1.cnt, (route->stack1.cnt == 0) ? 0.0 : route->stack1.array[route->stack1.cnt-1].priority);
		gfx_draw_text (NULL, 80, 80, text, &color[COLOR_yellow][3]);
		sprintf (text, "r->stack2: %d prio:%g", route->stack2.cnt, (route->stack2.cnt == 0) ? 0.0 : route->stack2.array[route->stack2.cnt-1].priority);
		gfx_draw_text (NULL, 80, 96, text, &color[COLOR_yellow][3]);
		sprintf (text, "r->stack3: %d prio:%g", route->stack3.cnt, (route->stack3.cnt == 0) ? 0.0 : route->stack3.array[route->stack3.cnt-1].priority);
		gfx_draw_text (NULL, 80, 112, text, &color[COLOR_yellow][3]);
		sprintf (text, "r->ways: %d", route->ways.cnt);
		gfx_draw_text (NULL, 80, 128, text, &color[COLOR_yellow][2]);
		sprintf (text, "r->route: %d", route->route.cnt);
		gfx_draw_text (NULL, 80, 144, text, &color[COLOR_yellow][3]);
	}

	/*
	 * draw the calculated route..
	 */
	rtlist = &route->route;
	tmplinestyle.width = 3;
	tmplinestyle.c = color[COLOR_redgray][3];
	draw_routelist (rtlist, tmplinestyle, -1);	
};



void draw_routelist (struct rtwaylist *rtlist, struct line_style linestyle, int cnt) {
	struct map_hash *mh;
	struct map_way *mw;
	iPoint p1, p2, center = {gfx_screensize.x/2, gfx_screensize.y/2};
	fPoint nd;
	int n, i, ps, pe;
	struct rtway* rtw = NULL;

	if (rtlist) for (i = 0; i < rtlist->cnt && (i < cnt || cnt == -1); i++) {
		rtw = &rtlist->array[i];
		mh = map_hash_get (rtw->pos.lon, rtw->pos.lat, MHLOAD_RELOAD);
		mw = map_way_find (mh, rtw->way.id, rtw->way.sid);
		// d_printf ("draw route %d: mw:%p id:%lld subid:%d pos:(%g,%g)", i, mw, route->ways.array[i].way.id, route->ways.array[i].way.sid,
		//   route->ways.array[i].pos.lon, route->ways.array[i].pos.lat );
		if (mw) {
			/* go through all the nodes */
			if (rtlist == &route->route && i < rtlist->cnt-1) {
				ps = rtlist->array[i].pnr;
			 	for (n = 0, pe = mw->p_cnt; n < mw->n_cnt; n++)
					if (mw->n[n].d_id == rtlist->array[i+1].way.id && mw->n[n].d_subid == rtlist->array[i+1].way.sid) {
						pe = mw->n[n].pnr;
					}
				if (pe < ps) {
					n = pe;
					pe = ps;
					ps = n;
				}
				pe++;
				if (pe >= mw->p_cnt) pe = mw->p_cnt;
				//d_printf ("%d %lld:%d ps:%d pe:%d", i, rtlist->array[i].way.id, rtlist->array[i].way.sid, ps, pe); 
			}
			else {
				ps = 0;
				pe = mw->p_cnt;
			}
					
 			for (n = ps; n < pe; n++) {
 				p2 = p1;
 				nd.x = map_lon2km (view_lon - mw->p[n].lon, mw->p[n].lat);
 				nd.y = map_lat2km (view_lat - mw->p[n].lat);
 				p1.x = center.x - (nd.x / view_scale);
 				p1.y = center.y + (nd.y / view_scale);
				if ((p1.x >= 0 && p1.x < gfx_screensize.x && p1.y >= 0 && p1.y < gfx_screensize.y) ||
				    (p2.x >= 0 && p2.x < gfx_screensize.x && p2.y >= 0 && p2.y < gfx_screensize.y)) {
	 				if (n > ps) {
						draw_lineway (NULL, p1.x, p1.y, p2.x, p2.y, linestyle);
					}
				}
 			}
			for (n = 0; n < mw->n_cnt; n++) {
				nd.x = map_lon2km (view_lon - mw->n[n].d.lon, mw->n[n].d.lat);
	 			nd.y = map_lat2km (view_lat - mw->n[n].d.lat);
	 			p1.x = center.x - (nd.x / view_scale);
	 			p1.y = center.y + (nd.y / view_scale);
	 			nd.x = map_lon2km (view_lon - mw->p[mw->n[n].pnr].lon, mw->p[mw->n[n].pnr].lat);
	 			nd.y = map_lat2km (view_lat - mw->p[mw->n[n].pnr].lat);
	 			p2.x = center.x - (nd.x / view_scale);
	 			p2.y = center.y + (nd.y / view_scale);
				if ((p1.x >= 0 && p1.x < gfx_screensize.x && p1.y >= 0 && p1.y < gfx_screensize.y) ||
				    (p2.x >= 0 && p2.x < gfx_screensize.x && p2.y >= 0 && p2.y < gfx_screensize.y)) {
		 				draw_lineway (NULL, p1.x, p1.y, p2.x, p2.y, linestyle);
					}
				}
			
		}	
	}
};
