/***************************************************************************
 *            map.h
 *
 *  Copyright  2009 - Steffen Pohle
 *  steffen@gulpe.de
 ****************************************************************************/

/*
 *  This program 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 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#ifndef _MAP_H_
#define _MAP_H_

#include <math.h>
#include <stdint.h>

#define MAP_EARTHRADIUS 6370.0
#define CALC_START(__pos, __step) (__step * floorf(__pos/__step))

#define MAP_W_REFS 8
#define MAP_W_NAMELEN 64

#define MAP_HASH_DEGFACTOR 80.0f
#define MAP_OSMWEB_DELTA 0.0125f

#define MAP_LSHASHFACTOR 80
#define MAP_LSFREECNT 4096
#if defined(__MINGW32CE__) || defined(_WIN32_WCE)
#define MAP_LSSTAT_MAX 16
#else
#define MAP_LSSTAT_MAX 128
#endif
#define MAP_LSSIZE_HASH 28
#define MAP_LSSIZE_WAY 14
#define MAP_LSSIZE_WAYNODE 23
#define MAP_LSSIZE_POS 8
#define MAP_LSSIZE_AREA 12
#define MAP_LSSIZE_PLACE 21
#define MAP_LSSIZE_POI 17

#define MAP_SEARCHLINE_LEN 128

#define MAP_HASH_DEFAULTSIZE 0x20000

#if defined(__MINGW32CE__) || defined(_WIN32_WCE)
#define MAP_HASH_MAX 128
#else
#define MAP_HASH_MAX 4096
#endif

#define MWAY_F_oneway     0x01
#define MWAY_F_planed     0x02
#define MWAY_F_roundabout 0x04
#define MWAY_F_railway    0x08
#define MWAY_F_junction   0x10
#define MWAY_F_TEXT "oneway\nplaned\nroundabout\nrailway\njunction"

#define MS_lock         0x01
#define MS_changed      0x02

enum _map_waytype {
	MWAY_highway,
	MWAY_tertiary,
	MWAY_railway,
	MWAY_residential,
	MWAY_cycleway,
	MWAY_footway,
	MWAY_service,
	MWAY_unknown_railway,
	MWAY_unknown_way,
	MWAY_unknown,
	MWAY_MAX
};

enum _map_areatype {
	MAREA_residential,
	MAREA_industrial,
	MAREA_water,
	MAREA_commercial,
	MAREA_greenfield,
	MAREA_farm,
	MAREA_wood,
	MAREA_land,
	MAREA_military,
	MAREA_building,
	MAREA_campsite,
	MAREA_unknown,
	MAREA_ignore,
	MAREA_MAX
};


enum _map_placetype {
	MAP_PLACE_city,
	MAP_PLACE_town,
	MAP_PLACE_village,
	MAP_PLACE_hamlet,
	MAP_PLACE_suburb,

	MAP_PLACE_unknown
};


enum _map_poitype {
	MAP_POI_gasstation,
	MAP_POI_parking,
	MAP_POI_trainstation,
	MAP_POI_busstop,
	MAP_POI_restaurant,
	MAP_POI_hotel,
	MAP_POI_campsite,

	MAP_POI_unknown
};

#include "osmroute.h"

struct map_pos {
	float lon;
	float lat;
};


struct map_hashpos {
	int ilon;
	int ilat;
};


struct map_waynode {
	int pnr;					// number of the point from the way
	struct map_pos d;			// destination (node address)
	unsigned long long int d_id;
	unsigned short int d_subid;
	int d_pnr;
	uint8_t flags;				// some flags.. like permitted
};


/*
 * way and area information
 */
struct map_way {
	char status;
	unsigned long long int id;
	unsigned short int subid;
	unsigned char type;
	unsigned char flags;
	char name[MAP_W_NAMELEN];
	char ref[MAP_W_NAMELEN];

	struct map_waynode *n;	/* connecting ways */
	int n_cnt;

	struct map_pos *p;  	/* point data */
	int p_cnt;

	struct map_way *next;   /* next */
	char data[];			/* memory for the point data */
};


struct map_area {
	char status;
	unsigned long long int id;
	unsigned short int subid;
	unsigned char type;
	unsigned char flags;
	
	struct map_pos *p;		/* point data */
	int p_cnt;
	
	struct map_area *prev;  /* prev */
	struct map_area *next;  /* next */
	char data[];			/* memory for the point data and name also additional data */
};


/*
 * places and pois
 */
struct map_poi {
	float lon;
	float lat;
	unsigned long long int id;			/* id how it is saved in openstreetmap */
	unsigned char type;					/* MAP_POI_RESTAURANT, MAP_POI_HOSPITAL, MAP_POI_UNDEFINED... */
	char *name;
	char *additional;

	struct map_poi *next;
	char data[];			/* data will contain: 1.NAME, 2.ADDITIONAL_DATA (seperated by \0) */
};


struct map_place {
	float lon;
	float lat;
	unsigned long long int id;
	unsigned char type;		/* MAP_P_VILLAGE, MAP_P_CITY, MAP_P_UNDEFINED... */
	unsigned int population;
	char *country;
	char *state;
	char *district;
	char *name;
	char *postalcode;

	struct map_place *next;
	char data[];
};


struct map_hash {
	char status;
	struct map_hashpos pos;

	int wayscnt;
	struct map_way *ways;
	int areascnt;
	struct map_area *areas;
	int poiscnt;
	struct map_poi *pois;
	int placescnt;
	struct map_place *places;

	char *free;		/* where is the next free datablock */
	int datasize;   /* how many bytes? */
	char data[];	/* data itself */
};


struct map_search_data {
	unsigned long long int id;
	float lon;
	float lat;
	char name[MAP_SEARCHLINE_LEN];
	char country[MAP_SEARCHLINE_LEN];
};


#define MHLOAD_NONE 0
#define MHLOAD_RELOAD 1
struct map_lshentry {
	uint32_t ways;
	uint32_t areas;
	uint32_t pois;
	uint32_t places;
	uint32_t pcnt;
	uint32_t ncnt;
	uint32_t ccnt;		/* size of all text based data (including '0') */
};


struct map_lshmap {
	uint64_t pos;
	uint32_t size;
};


/*
 * as soon as we have different r_fd and w_fd the filename will 
 * be the one from the orginal file
 */
struct map_lsstat {
	char fname[LEN_FILENAME];
	char fnametmp[LEN_FILENAME];
	struct map_lshmap r_lshpos[MAP_LSHASHFACTOR*MAP_LSHASHFACTOR];	/* size of array is always MAP_LSHASHFACTOR*MAP_LSHASHFACTOR */
	struct map_lshmap w_lshpos[MAP_LSHASHFACTOR*MAP_LSHASHFACTOR];	/* size of array is always MAP_LSHASHFACTOR*MAP_LSHASHFACTOR */
	struct map_lshmap w_free[MAP_LSFREECNT];						/* data where we handle the free datablocks */
	int r_fd;						/* read filedescriptor  */
	int w_fd;						/* write filedescriptor */
	int changed;
};


extern struct map_hash **mhash;
extern int mhash_max;						// currently allocated entrys
extern int mhash_pos;
extern struct map_lsstat *mlsstat;


// extern unsigned long long int selected_way_id;
// extern unsigned short int selected_way_sid;
// extern struct map_pos selected_way_pos[2];
// extern char selected_way_name[MAP_W_NAMELEN];


/*
 * some calculations 
 */
extern float map_lon2km (float lon, float lat);
extern float map_lat2km (float lat);
extern float map_km2lon (float km, float lat);
extern float map_km2lat (float km);
extern int map_text2geo (char *text, float *dest);

extern int map_geo2igeo (float f);
extern float map_igeo2geo (int i);
extern struct map_hashpos map_pos2ipos (struct map_pos pos);

extern float map_getdistance (struct map_pos p1, struct map_pos p2);

/*
 * general map functions
 */
extern void map_init ();
extern void map_clear ();				// free the used memory
extern void map_debug ();


/*
 * hash handling
 */
extern struct map_hash *map_hash_alloc (int memsize);				// alloc memory for the hash
extern struct map_hash *map_hash_realloc (struct map_hash *mhorg, int memsize); // realloc hash memory and copy data into it
extern void map_hash_copy (struct map_hash *mhdest,struct map_hash *mhsrc);
extern int map_hash_calc_size (int ways, int areas, int pois, int places, int pcnt, int ncnt, int ccnt);
extern struct map_hash *map_hash_geti (int ilon, int ilat, int loadflags);
extern struct map_hash *map_hash_get (float lon, float lat, int loadflags);
extern int map_hash_add (struct map_hash *mh); // add/update hash
extern void map_hash_free (struct map_hash *mh, int noremove); // save and remove hash from memory (also delete from list)
extern int map_hash_getfree_size (struct map_hash *mh);
extern void *map_hash_getfree_aligned (struct map_hash *mh, int align);
extern int map_hash_countways (struct map_hash *mh);
extern int map_hash_countareas (struct map_hash *mh);


/*
 * load / save from the data dir 
 */
extern struct map_hash *map_load_hash (int ilon, int ilat);
extern void map_save_all ();
extern int map_save_hash (struct map_hash *mh);

extern void map_ls_rwdatacheck (int size);
extern void map_ls_get_filename_only (char *fn, int len, int ilon, int ilat);
extern void map_ls_get_filename (char *fn, int len, int ilon, int ilat);
extern struct map_lsstat *map_ls_statopen (char *fname);
extern struct map_lsstat *map_ls_statget (char *fname);
extern void map_ls_statclose (struct map_lsstat *lsstat);
extern char *map_ls_loaddata (struct map_lsstat *lsstat, int *size, int ilon, int ilat);
extern void map_ls_savedata (struct map_lsstat *lsstat, char *data, int size, int ilon, int ilat);
extern char *map_ls_hash2data (struct map_hash *mh, int *size);
extern struct map_hash *map_ls_data2hash (char *data, int size);

extern void map_defragfile (char *fn);
extern void map_defrag ();

/*
 * load data from file / web 
 */
extern void osm_loadfile (char *fn);
extern void map_load_web (struct map_pos hs, struct map_pos he);
extern void map_load_setview ();
extern int map_webload (char *remotefn, char *localfn, char *statustext);
extern void map_refresh (float lon, float lat);
extern void map_refreshblock (struct map_pos start, struct map_pos end, float delta);


/*
 * way/node with the givin ID 
 */
extern struct map_way *map_way_find (struct map_hash *mh, unsigned long long int id, unsigned short int subid);
extern void map_way_copy (struct map_way *dest, struct map_way *src);
extern int map_way_add (struct map_way *way, int loadflags);
extern int map_way_add_to_hash (struct map_hash *mh, struct map_way *mw);
extern int map_way_append_to_hash (struct map_hash *mh, struct map_way *mw);
extern int map_way_getsize (struct map_way *way);
extern int map_way_findclosest (struct map_pos *pos, struct map_pos *waypos, int idh, char *name, int namelen, unsigned long long int *closest_id, unsigned short int *closest_sid);
extern float map_way_getdistance (struct map_way *mw, struct map_pos *pos, struct map_pos *waypos);
extern float map_way_getlenght (struct map_way *mw, int start, int end);
extern int map_way_checkref (char *ref1, char *ref2);


/*
 * find the area/node with the givin ID 
 */
extern struct map_area *map_area_find (struct map_hash *mh, unsigned long long int id);
extern void map_area_copy (struct map_area *dest, struct map_area *src);
extern int map_area_add (struct map_area *area, int loadflags);
extern int map_area_add_to_hash (struct map_hash *mh, struct map_area *ma);
extern int map_area_append_to_hash (struct map_hash *mh, struct map_area *ma);
extern int map_area_getsize (struct map_area *area);


/*
 * pois and places
 */
extern void map_place_copy (struct map_place *dest, struct map_place *src);
extern int map_place_add (struct map_place *place, int loadflags);
extern int map_place_add_to_hash (struct map_hash *mh, struct map_place *place);
extern int map_place_getsize (struct map_place *place);

extern void map_poi_copy (struct map_poi *dest, struct map_poi *src);
extern int map_poi_add (struct map_poi *poi, int loadflags);
extern int map_poi_add_to_hash (struct map_hash *mh, struct map_poi *poi);
extern int map_poi_getsize (struct map_poi *poi);


/* 
 * debugging functions 
 */
extern void map_way_print (struct map_way *mw);


/*
 * searching stuff
 */
extern void map_search_add (char *country, char *name, unsigned long long int id, float lon, float lat);
extern int map_search (char *name, struct map_search_data *data, int datasize);
extern void map_search_init ();
extern void map_search_get_filename (char *fn, int len);
extern void map_search_sort ();

/*
 * for statistics or other informations.
 */
extern unsigned long long int osm_cur_wayid;
extern unsigned long long int osm_ways_cnt;
extern unsigned long long int osm_nodes_cnt;
extern float osm_file_pos;
extern struct map_pos osm_load_from_web_cur;
extern struct map_pos osm_load_from_web_start;
extern struct map_pos osm_load_from_web_end;


#ifdef HAVE_NCURSES
void osm_convert_info ();
#endif

#endif
