/*
 * draw_gui.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 "gps.h"
#include "system.h"
#include "gui.h"
#include "routing.h"
#include "favorites.h"
#include "vector.h"
#include "memoryleak.h"


/*
 * mouse variables
 */
iPoint mousepos;
int mousebtn;
time_t mousebtnpresstime;
iPoint mousebtnpresspos = {0.0, 0.0};
struct map_pos mousebtnpressgpos = {0, 0};
int mousebtnpresslongtime = 0;
unsigned long long int mouse_over_way_id = 0;
unsigned short int mouse_over_way_sid = 0;
char mouse_over_way_name[MAP_W_NAMELEN] = "\0";




/*****************************************************************
 * draw mouse move
 * if btn == -1 mean no button pressed or selected
 */
void draw_mousemove (int x, int y, int btn) {
	float lon, lat, lonold, latold;

	mousepos.x = x;
	mousepos.y = y;
	if (mousebtn) {
		latold = -map_km2lat(((float)(mousebtnpresspos.y-gfx_screensize.y/2)) * view_scale);
		lonold = map_km2lon(((float)(mousebtnpresspos.x-gfx_screensize.x/2)) * view_scale, view_lat + latold);

		lat = -map_km2lat(((float)(y-gfx_screensize.y/2)) * view_scale);
		lon = map_km2lon(((float)(x-gfx_screensize.x/2)) * view_scale, view_lat + lat);

		lat = lat - latold;
		lon = lon - lonold;

		view_lat = mousebtnpressgpos.lat - lat;
		view_lon = mousebtnpressgpos.lon - lon;
		draw_del_flag (DRAW_GPSFOLLOW);
	}
	draw ();
};


void draw_mousebtndown (int x, int y, int btn) {
	mousebtnpresstime = time (NULL);
	mousebtnpresspos.x = x;
	mousebtnpresspos.y = y;
	mousebtnpressgpos.lon = view_lon;
	mousebtnpressgpos.lat = view_lat;
	mousebtn = btn;
	mousebtnpresslongtime = 0;
	draw ();
};


void draw_mousebtnup (int x, int y, int btn)
{
	time_t t = time(NULL);
	float lon, lat;
	int dx, dy;
	
	if (!mousebtn) return;	/* button is no longer pressed */
	mousebtn = 0;

	/* check for debugging routeing problems */
	if (route && y > gfx_screensize.y-32 && y < gfx_screensize.y && x > 0 && x < 100 ) {
		view_lon = route->closest_lon;
		view_lat = route->closest_lat;
		draw_del_flag (DRAW_GPSFOLLOW);
	} 
	else {
		lat = -map_km2lat(((float)(y-gfx_screensize.y/2)) * view_scale);
		lon = map_km2lon(((float)(x-gfx_screensize.x/2)) * view_scale, view_lat + lat);

		dx = abs (mousebtnpresspos.x-x)*100/gfx_screensize.x;
		dy = abs (mousebtnpresspos.y-y)*100/gfx_screensize.y;
	
		/* short time button pressing */
		d_printf ("released mouse button..");
		if (t - mousebtnpresstime <= 1)	{
			if (dx < 10 && dy < 10) {
				if (select_enabled)	{
					select_enabled = 0;
				}
				else {
					select_enabled = 1;
					select_pos.lat = view_lat + lat;
					select_pos.lon = view_lon + lon;
				}
			}
		}
		else if (mousebtnpresslongtime && dx < 10 && dy < 10) {
			/* long time button pressed */
			wnd_mapcontext_show ();
		}
	}

	draw ();
};


void draw_mouseloop () {
	time_t t = time(NULL);
	
	if (mousebtn && t - mousebtnpresstime > 1) {
		mousebtnpresslongtime = 1;
		d_printf ("draw_mouseloop: long press..");
		draw ();
	}
		
	return;
};


void draw_gui () {
	struct line_style tmplinestyle;
	struct line_style ls;
	iPoint p1, p2, center = {gfx_screensize.x/2, gfx_screensize.y/2};
	struct map_pos pos;
	int n, n1;
	float lon, lat;
	char text[64];
	struct map_hash *mh = NULL;
	struct map_way *mw = NULL;

	draw_gui_route ();
	draw_gui_favorites ();
	draw_gui_gps ();

	/*
	 * read current way where the mouse is over at
	 */
	draw_screen2geo (mousepos.x, mousepos.y, &lon, &lat);
	if (app.status == APPSTATUS_nothing) mh = map_hash_get (lon, lat, MHLOAD_RELOAD);
	else mh = map_hash_get (lon, lat, MHLOAD_NONE);
	pos.lon = lon;
 	pos.lat = lat;
	map_way_findclosest (&pos, NULL, 0, NULL, 0, &mouse_over_way_id, &mouse_over_way_sid);
	
	/*
	 * our mouse cursor 
	 */
	tmplinestyle.width = 2.0;
	if (mousebtnpresslongtime && mousebtn)
		tmplinestyle.c = tmplinestyle.borderc = color[COLOR_red][2];
	else
		tmplinestyle.c = tmplinestyle.borderc = color[COLOR_white][3];
	draw_line (NULL, mousepos.x-5, mousepos.y-5, mousepos.x+5, mousepos.y+5, tmplinestyle);
	draw_line (NULL, mousepos.x+5, mousepos.y-5, mousepos.x-5, mousepos.y+5, tmplinestyle);

	/*
	 * draw selected position
	 */
	if (select_enabled) {
		p1 = draw_geo2screen (view_lon, view_lat, select_pos.lon, select_pos.lat);
		p1.x += center.x;
		p1.y += center.y;
		tmplinestyle.c = tmplinestyle.borderc = color[COLOR_bluegray][3];
		draw_line (NULL, p1.x, p1.y-5, p1.x, p1.y+5, tmplinestyle);
		draw_line (NULL, p1.x-5, p1.y, p1.x+5, p1.y, tmplinestyle);
		
		draw_screen2geo (mousepos.x, mousepos.y, &pos.lon, &pos.lat);
		lon = map_getdistance (select_pos, pos);
		sprintf (text, _("Select Distance:%g"), lon);
		gfx_draw_text (NULL, 0, gfx_screensize.y-32, text, &color[COLOR_white][3]);
	}

	/*
	 * statusline 
	 */
	if (app.status != APPSTATUS_nothing) {
		struct line_style ls;
		
		ls.width = 1.0;
		ls.c = ls.borderc = color[COLOR_white][3];

		p1.x = gfx_screensize.x/2-101;
		p2.x = gfx_screensize.x/2+101;
		p1.y = gfx_screensize.y-32;
		p2.y = gfx_screensize.y-10;

		draw_polygonstart ();
		draw_polygonadd (p1.x, p1.y);
		draw_polygonadd (p2.x, p1.y);
		draw_polygonadd (p2.x, p2.y);
		draw_polygonadd (p1.x, p2.y);
		draw_polygonfinish (NULL, ls, &color[COLOR_white][0], 1);
		
		p1.x = gfx_screensize.x/2-(float)(100.0*app.statusline_progress);
		p2.x = gfx_screensize.x/2+(float)(100.0*app.statusline_progress);
		p1.y = gfx_screensize.y-31;
		p2.y = gfx_screensize.y-11;

		draw_polygonstart ();
		draw_polygonadd (p1.x, p1.y);
		draw_polygonadd (p2.x, p1.y);
		draw_polygonadd (p2.x, p2.y);
		draw_polygonadd (p1.x, p2.y);
		draw_polygonfinish (NULL, ls, &color[COLOR_blue][3], 0);

		gfx_draw_text (NULL, gfx_screensize.x/2-98, p1.y + 2, app.statusline_text, &color[COLOR_white][3]);
	}

	/*
	 * draw additional debugging informations
	 */
	if (view_flags & DRAW_DEBUG) {
		struct memoryleak_info mi;
	 	struct map_hash *mh1;
	 	struct map_way *mw1;
	 	iPoint p1, p2;
	 	fPoint nd;

		/* draw vorner markings */
		ls.width = 1.0;
		ls.c = ls.borderc = color[COLOR_pink][2];
		p1.x = gfx_screensize.x;
		p1.y = gfx_screensize.y;
		gfx_draw_line (NULL, 1, 1, 6, 6, ls);
		gfx_draw_line (NULL, 1, p1.y-1, 6, p1.y-6, ls);
		gfx_draw_line (NULL, p1.x-1, p1.y-1, p1.x-6, p1.y-6, ls);
		gfx_draw_line (NULL, p1.x-1, 1, p1.x-6, 6, ls);

		/* draw scale */
		sprintf (text, "Scale:%g m/px", view_scale * 1000.0);
		gfx_draw_text (NULL, 80, 40, text, &color[COLOR_white][3]);

		/* memory information */
		ml_get_stats (&mi);
		sprintf (text, "mem: %d kB [%d]", (int)(mi.size/1024), (int)mi.blocks);
		gfx_draw_text (NULL, 80, 56, text, &color[COLOR_white][3]);
			
		/* draw the way */
		mw = map_way_find (mh, mouse_over_way_id, mouse_over_way_sid);
		if (mw && draw_type[mw->type]) {
			/* go through all the nodes */
			tmplinestyle.width = 3;
 			tmplinestyle.c = color[COLOR_pink][2];
 			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) {
					tmplinestyle.width = 3;
					tmplinestyle.c = color[COLOR_pink][3];
					draw_lineway (NULL, p1.x, p1.y, p2.x, p2.y, tmplinestyle);
				}
				if (n == 0) {
	 				tmplinestyle.c = color[COLOR_greengray][3];
					tmplinestyle.width = 0;
 					draw_lineway (NULL, p1.x, p1.y-10, p1.x, p1.y+10, tmplinestyle);
 					draw_lineway (NULL, p1.x+10, p1.y, p1.x-10, p1.y, tmplinestyle);
				}
				else {
 					tmplinestyle.c = color[COLOR_green][3];
					tmplinestyle.width = 0;
 					draw_lineway (NULL, p1.x, p1.y-5, p1.x, p1.y+5, tmplinestyle);
 					draw_lineway (NULL, p1.x+5, p1.y, p1.x-5, p1.y, tmplinestyle);
				}
 			}
 	
 			/* draw the waynodes and connected way */
 			for (n = 0; n < mw->n_cnt; n++) if (mw->n[n].pnr < mw->p_cnt) {
 				p1 = draw_geo2screen (view_lon, view_lat, mw->n[n].d.lon, mw->n[n].d.lat);
 				p2 = draw_geo2screen (view_lon, view_lat, mw->p[mw->n[n].pnr].lon, mw->p[mw->n[n].pnr].lat);
 				p1.x += center.x;
 				p1.y += center.y;
 				p2.x += center.x;
 				p2.y += center.y;
				tmplinestyle.width = 0;
 				tmplinestyle.c = color[COLOR_red][3];
 				draw_lineway (NULL, p1.x, p1.y, p2.x, p2.y, tmplinestyle);
 				tmplinestyle.width = 0;
 				tmplinestyle.c = color[COLOR_red][2];
 				draw_lineway (NULL, p2.x-5, p2.y-5, p2.x+5, p2.y+5, tmplinestyle);
 				draw_lineway (NULL, p2.x+5, p2.y-5, p2.x-5, p2.y+5, tmplinestyle);

				mh1 = map_hash_get (mw->n[n].d.lon, mw->n[n].d.lat, MHLOAD_RELOAD);
				mw1 = map_way_find (mh1, mw->n[n].d_id, mw->n[n].d_subid);
				if (mw1) {
					/* go through all the nodes */
					tmplinestyle.width = 3;
		 			tmplinestyle.c = color[COLOR_pink][3];
		 			for (n1 = 0; n1 < mw1->p_cnt; n1++) {
		 				p2 = p1;
		 				nd.x = map_lon2km (view_lon - mw1->p[n1].lon, mw1->p[n1].lat);
		 				nd.y = map_lat2km (view_lat - mw1->p[n1].lat);
		 				p1.x = center.x - (nd.x / view_scale);
		 				p1.y = center.y + (nd.y / view_scale);
		 				if (n1 > 0) {
							tmplinestyle.width = 3;
							tmplinestyle.c = color[COLOR_pink][1];
							draw_lineway (NULL, p1.x, p1.y, p2.x, p2.y, tmplinestyle);
						}
		 			}
				}
				else 
					 d_printf ("can not find way. %g:%g   id:%lld subid:%d", mw->n[n].d.lon, mw->n[n].d.lat, mw->n[n].d_id, mw->n[n].d_subid);
			}
			/* 6displaying informations */
			sprintf (text, "name:%s flags:%d type:%d", mw->name, mw->flags, mw->type);
			gfx_draw_text (NULL, mousepos.x, mousepos.y-24, text, &color[COLOR_white][3]);
			sprintf (text, "len:%g ref:%s", map_way_getlenght (mw, -1, -1), mw->ref);
			gfx_draw_text (NULL, mousepos.x, mousepos.y-12, text, &color[COLOR_white][3]);
			sprintf (text, "ipos:%d,%d pcnt:%d ncnt:%d", mh->pos.ilon, mh->pos.ilat, mw->p_cnt, mw->n_cnt);
			gfx_draw_text (NULL, mousepos.x, mousepos.y-48, text, &color[COLOR_white][3]);
			sprintf (text, "pos:%g,%g  ipos:%d,%d", mw->p[0].lon, mw->p[0].lat, map_geo2igeo (mw->p[0].lon), map_geo2igeo (mw->p[0].lat));
			gfx_draw_text (NULL, mousepos.x, mousepos.y-36, text, &color[COLOR_white][3]);
 		}	
		/* highlight way under cursor */
		if (mouse_over_way_id != 0) {
			sprintf (text, "id:%lld:%d", mouse_over_way_id, mouse_over_way_sid);
			gfx_draw_text (NULL, mousepos.x, mousepos.y, text, &color[COLOR_white][3]);
		}
	}
	
	gui_draw ();
};
