/*
 *
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include <stdlib.h>
#include <windows.h>
#include <commctrl.h>
#include <winbase.h>
#include <tchar.h>
#include <dirent.h>
#if defined(__MINGW32CE__) || defined(_WIN32_WCE)
	#include <aygshell.h>
#endif

#include <mmsystem.h>

#include <shlobj.h>
#include "osmroute.h"
#include "wince_port.h"
#include "gps.h"
#include "system.h"

#define MENU_HEIGHT 26
#define DIALOG_TEXTLEN 128

static char _get_path_[MAX_PATH];
char dialog_filename[LEN_FILENAME];
BOOL CALLBACK GpsSettingProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam);


#if defined(__MINGW32CE__) || defined(_WIN32_WCE)
char *wince_get_path (HWND hWnd, WCHAR *filter, int selectpath) {
	WCHAR fn[260];
#else
char *wince_get_path (HWND hWnd, char *filter, int selectpath) {
	char fn[260];
#endif

	OPENFILENAME ofn;       // common dialog box structure
	int ret;
	
	// Initialize OPENFILENAME
	ZeroMemory(&ofn, sizeof(ofn));
	ZeroMemory(_get_path_, MAX_PATH);
	ofn.lStructSize = sizeof(ofn);
	ofn.hwndOwner = hWnd;
#if defined(__MINGW32CE__) || defined(_WIN32_WCE)
	// Set lpstrFile[0] to '\0' so that GetOpenFileName does not 
	// use the contents of szFile to initialize itself.
	ofn.lpstrFile = fn;
	*fn = 0;
//	ofn.lpstrFilter = L"Mapdata\0*.mapdata\0All\0*.*\0";
	ofn.lpstrFilter = filter;
#else
	ofn.lpstrFile = fn;
	*fn = 0;
	ofn.lpstrFilter = filter;
#endif
	ofn.nMaxFile = MAX_PATH;
	ofn.lpstrFileTitle = NULL;
	ofn.nMaxFileTitle = 0;
	ofn.nFilterIndex = 1;
	ofn.lpstrInitialDir = NULL;
	ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;

	// Display the Open dialog box. 
	ret = GetOpenFileName(&ofn);

	if (ret==TRUE) {
		int i, j;
#if defined(__MINGW32CE__) || defined(_WIN32_WCE)
		int fnlen = lstrlenW(fn); // Convert all UNICODE characters
		WideCharToMultiByte( CP_ACP, 0, fn, fnlen, _get_path_, MAX_PATH, NULL, NULL );
#else
	    strncpy (_get_path_, fn, MAX_PATH);
#endif
		if (selectpath) {
			for (i = 0, j = 0; i < strlen (_get_path_); i++) {
				if (_get_path_[i] == '\\') j = i+1;
			}
			_get_path_[j] = 0;
		}
		d_printf ("selected file/path: %s", _get_path_);
		return _get_path_;
	}
	else
		return NULL;
};


#if defined(__MINGW32CE__) || defined(_WIN32_WCE)
char *wince_get_pathsave (HWND hWnd, WCHAR *filter, int selectpath) {
	WCHAR fn[260];
#else
char *wince_get_pathsave (HWND hWnd, char *filter, int selectpath) {
	char fn[260];
#endif

	OPENFILENAME sfn;       // common dialog box structure
	int ret;
	
	// Initialize OPENFILENAME
	ZeroMemory(&sfn, sizeof(sfn));
	ZeroMemory(_get_path_, MAX_PATH);
	sfn.lStructSize = sizeof(sfn);
	sfn.hwndOwner = hWnd;
#if defined(__MINGW32CE__) || defined(_WIN32_WCE)
	// Set lpstrFile[0] to '\0' so that GetOpenFileName does not 
	// use the contents of szFile to initialize itself.
	sfn.lpstrFile = fn;
	*fn = 0;
//	ofn.lpstrFilter = L"Mapdata\0*.mapdata\0All\0*.*\0";
	sfn.lpstrFilter = filter;
#else
	sfn.lpstrFile = fn;
	*fn = 0;
	sfn.lpstrFilter = filter;
#endif
	sfn.nMaxFile = MAX_PATH;
	sfn.lpstrFileTitle = NULL;
	sfn.nMaxFileTitle = 0;
	sfn.nFilterIndex = 1;
	sfn.lpstrInitialDir = NULL;
	sfn.Flags = 0;

	// Display the Open dialog box. 
	ret = GetSaveFileName(&sfn);

	if (ret==TRUE) {
		int i, j;
#if defined(__MINGW32CE__) || defined(_WIN32_WCE)
		int fnlen = lstrlenW(fn); // Convert all UNICODE characters
		WideCharToMultiByte( CP_ACP, 0, fn, fnlen, _get_path_, MAX_PATH, NULL, NULL );
#else
	    strncpy (_get_path_, fn, MAX_PATH);
#endif
		if (selectpath) {
			for (i = 0, j = 0; i < strlen (_get_path_); i++) {
				if (_get_path_[i] == '\\') j = i+1;
			}
			_get_path_[j] = 0;
		}
		d_printf ("selected file/path: %s", _get_path_);
		return _get_path_;
	}
	else
		return NULL;
};

/********************************************************************
 *
 * dialog_getfilename
 */
char *dialog_getfilename (char *caption, char *filter, int save) {
	char *fn;
#if defined(__MINGW32CE__) || defined(_WIN32_WCE)
	WCHAR f[256];
	char *c;
	int i, convert;

	for (i = 0, c = filter; c[i] != 0; i = i + strlen(c+i) + 1)
		d_printf ("i:%d, c:%s", i, &c[i]);

    convert = MultiByteToWideChar(CP_ACP, 0, filter, i, f, 256);
	d_printf ("convert:%d  i:%d", convert, i);
#else
	char *f = filter;
#endif
	
	if (save)
		fn = wince_get_pathsave (hMainWnd, f, FALSE);
	else fn = wince_get_path (hMainWnd, f, FALSE);

	return fn;
};



/********************************************************************
 *
 * gpsroute data... needed to convert to gpx and prepared for 
 * openstreetmap
 *
 */
BOOL CALLBACK TextEditProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam);
char edittext_label[DIALOG_TEXTLEN];
char edittext_data[DIALOG_TEXTLEN];
char edittext_caption[DIALOG_TEXTLEN];

char *textedit_dialog (char *caption, char *label, char *data) {
	strncpy (edittext_label, label, DIALOG_TEXTLEN);
	strncpy (edittext_data, data, DIALOG_TEXTLEN);
	strncpy (edittext_caption, caption, DIALOG_TEXTLEN);

	if (DialogBox(hi, MAKEINTRESOURCE(IDR_TEXTEDIT), hMainWnd, (DLGPROC)TextEditProc)!=IDOK) {
		return NULL;
	}
	else {
		return edittext_data;
	}

	return NULL;
};


BOOL CALLBACK TextEditProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) { 
#if defined(__MINGW32CE__) || defined(_WIN32_WCE)
	WCHAR text_[DIALOG_TEXTLEN];
#endif

	switch (message) { 
		case WM_INITDIALOG:
#if defined(__MINGW32CE__) || defined(_WIN32_WCE)
			char2wchar (text_, DIALOG_TEXTLEN,  edittext_data);
			SetDlgItemText(hwndDlg, IDC_EDIT, text_);
#else
			SetDlgItemText(hwndDlg, IDC_EDIT, edittext_data);
#endif
			break;
        case WM_COMMAND:
            switch (LOWORD(wParam)) 
            { 
                case IDOK: 
#if defined(__MINGW32CE__) || defined(_WIN32_WCE)
					GetDlgItemText(hwndDlg, IDC_EDIT, text_, DIALOG_TEXTLEN);
					wchar2char (edittext_data, DIALOG_TEXTLEN,  text_);
#else
					GetDlgItemText(hwndDlg, IDC_EDIT, edittext_data, DIALOG_TEXTLEN);
#endif
                case IDCANCEL: 
                    EndDialog(hwndDlg, wParam); 
                    return TRUE;
					break;
			}
    } 
    return FALSE; 
};
 

/******************************************************************************
 * GPS Dialog for windows and windows ce.
 */
void gps_wince_settings () {
	int oldbaudrate;
	int oldcomport;
	int oldflags;
	
	gps_serial_settings_read_device ();
	gps_wince_device[0] = '\0';
	oldbaudrate = gps_serial_baudrate;
	oldcomport = gps_serial_comport;
	oldflags = gpsflags;

	if (DialogBox(hi, MAKEINTRESOURCE(IDR_COMSETTING), hMainWnd, (DLGPROC)GpsSettingProc)!=IDOK) {
		gps_serial_baudrate = oldbaudrate;
		gps_serial_comport = oldcomport;
		gpsflags = oldflags;
		gps_serial_settings_read_device ();
	}
	else {
		/* convert selected comport and baudrate into the config text. */
		if (gps_wince_device[0] != '\0') {
			d_printf ("selected gps device: %s", gps_wince_device);
			gps_set_device (gps_wince_device);
		}
	}

	return;
};

BOOL CALLBACK GpsSettingProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) { 
	char txt[GPS_DEVICELEN];
	char *ptxt;

	switch (message) { 
		case WM_INITDIALOG:
			ptxt = gps_get_device ();
			if (strncmp (ptxt, "file:sim,", 9) == 0) 
				CheckDlgButton(hwndDlg, IDC_SIMMULATION, BST_CHECKED);
			else 
				CheckDlgButton(hwndDlg, IDC_SIMMULATION, BST_UNCHECKED);
			SetDlgItemText_wa(hwndDlg, IDC_DEVEDIT, ptxt);
			CheckDlgButton(hwndDlg, IDC_CREATELOG, (gpsflags & GPSF_LOG) ? BST_CHECKED : BST_UNCHECKED);
			CheckRadioButton(hwndDlg, IDC_COMPORT1, IDC_COMPORT2, IDC_COMPORT1+gps_serial_comport);
            CheckRadioButton(hwndDlg, IDC_BAUD1, IDC_BAUD8, IDC_BAUD1+gps_serial_baudrate);
			break;
        case WM_COMMAND:
            switch (LOWORD(wParam)) 
            { 
                case IDOK: 
					GetDlgItemText_wa(hwndDlg, IDC_DEVEDIT, gps_wince_device, GPS_DEVICELEN);
                case IDCANCEL: 
                    EndDialog(hwndDlg, wParam); 
                    return TRUE;
					break;
				case IDC_COMPORT1:
				case IDC_COMPORT2:
                    gps_serial_comport = LOWORD(wParam)-IDC_COMPORT1;
                    CheckRadioButton(hwndDlg, IDC_COMPORT1, IDC_COMPORT2, LOWORD(wParam));
					sprintf (txt, "serial:com%d,%d", gps_serial_comport+1, gps_serial_baudratearray[gps_serial_baudrate]);
					SetDlgItemText_wa(hwndDlg, IDC_DEVEDIT, txt);
					break;
				case IDC_CREATELOG: {
						int checked = !(IsDlgButtonChecked (hwndDlg, IDC_CREATELOG) == BST_CHECKED);
						CheckDlgButton( hwndDlg, IDC_CREATELOG, checked ? BST_CHECKED : BST_UNCHECKED);
						if (checked) gpsflags = gpsflags | GPSF_LOG;
						else gpsflags = gpsflags & (GPSF_ALL-GPSF_LOG);
					}
					break;
				case IDC_SIMMULATION: {
						int checked = !(IsDlgButtonChecked (hwndDlg, IDC_SIMMULATION) == BST_CHECKED);
						char txt1[GPS_DEVICELEN];

						/* check if there has one file been selected */
						GetDlgItemText_wa(hwndDlg, IDC_DEVEDIT, txt1, GPS_DEVICELEN);
						if (strncmp (txt1, "file:sim,", 9) == 0)
							ptxt = txt1+9;
						else if (strncmp (txt1, "file:", 5) == 0)
							ptxt = txt1+5;
						else {
							ptxt = txt1;
							txt1[0] = 0;
						}

						/* set the new text */
                   		CheckDlgButton( hwndDlg, IDC_SIMMULATION, checked ? BST_CHECKED : BST_UNCHECKED );
						if (checked) {
							sprintf (txt, "file:sim,%s", ptxt);
						}
						else {
							sprintf (txt, "file:%s", ptxt);
						}
						SetDlgItemText_wa (hwndDlg, IDC_DEVEDIT, txt);
					
						break;
					}
				case IDC_BAUD1:
				case IDC_BAUD2:
				case IDC_BAUD3:
				case IDC_BAUD4:
				case IDC_BAUD5:
				case IDC_BAUD6:
				case IDC_BAUD7:
				case IDC_BAUD8:
                    gps_serial_baudrate = LOWORD(wParam)-IDC_BAUD1;
                    CheckRadioButton(hwndDlg, IDC_BAUD1, IDC_BAUD8, LOWORD(wParam));
					sprintf (txt, "serial:com%d,%d", gps_serial_comport+1, gps_serial_baudratearray[gps_serial_baudrate]);
					SetDlgItemText_wa(hwndDlg, IDC_DEVEDIT, txt);
					break;
                case IDC_FILE:
					{
						char *fn;
#if defined(__MINGW32CE__) || defined(_WIN32_WCE)
						fn = wince_get_path (hwndDlg, L"NMEA-Datei\0*.nmea\0All\0*.*\0", FALSE);
#else
						fn = wince_get_path (hwndDlg, "NMEA\0*.nmea\0All\0*.*\0", FALSE);
#endif
						if (fn) {
							if (IsDlgButtonChecked (hwndDlg, IDC_SIMMULATION) == BST_CHECKED)
								snprintf (txt, GPS_DEVICELEN, "file:sim,%s", fn);
							else 
								snprintf (txt, GPS_DEVICELEN, "file:%s", fn);
						}					
					}
					SetDlgItemText_wa(hwndDlg, IDC_DEVEDIT, txt);
					break;
			}
    } 
    return FALSE; 
};



/********************************************************************
 *
 * gpsroute data... needed to convert to gpx and prepared for 
 * openstreetmap
 *
 */
char select_dir_path[LEN_FILENAME];
char select_dir_caption[LEN_FILENAME];
BOOL CALLBACK SelDirProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam);

/*
 * refresh directory list
 */
void select_dir_refresh (HWND hwndDlg, char *path) {
#if defined(__MINGW32CE__) || defined(_WIN32_WCE)
	int i;
	WCHAR text_[LEN_FILENAME];
#endif
	DIR *d;
	struct dirent *de;
	HWND listbox = GetDlgItem(hwndDlg, IDC_DIRLIST);
	char tmppath[LEN_FILENAME];

	/* delete list */		
	SendMessage(listbox, LB_RESETCONTENT, 0, 0);
	d_printf ("clear list");

	#if defined(__MINGW32CE__) || defined(_WIN32_WCE)
	i = char2wchar (text_, LEN_FILENAME, "..");
	text_[i] = 0;
	SendMessage(listbox, LB_ADDSTRING, 0, (LPARAM) text_);
	#else
	SendMessage(listbox, LB_ADDSTRING, 0, (LPARAM) "..");
	#endif
	
	/* read directory */
	d = opendir (path);
	if (d != NULL) {
		de = readdir (d);
		while (de) {
			/* add to list */
			if (path[strlen(path)-1] == DIR_SEP)
				snprintf (tmppath, LEN_FILENAME, "%s%s", path, de->d_name);
			else
				snprintf (tmppath, LEN_FILENAME, "%s%c%s", path, DIR_SEP, de->d_name);
			if (dir_exist (tmppath) && de->d_name[0] != '.') {
				#if defined(__MINGW32CE__) || defined(_WIN32_WCE)
					i = char2wchar (text_, LEN_FILENAME, de->d_name);
					text_[i] = 0;
					SendMessage(listbox, LB_ADDSTRING, 0, (LPARAM) text_);
				#else
					SendMessage(listbox, LB_ADDSTRING, 0, (LPARAM) de->d_name);
				#endif
			}
			de = readdir (d);
		} while (de);
		closedir (d);
	}
};


char *select_dir_dialog (char *caption, char *data) {
	strncpy (select_dir_path, data, LEN_FILENAME);
	strncpy (select_dir_caption, caption, LEN_FILENAME);
	if (DialogBox(hi, MAKEINTRESOURCE(IDR_SELECT_DIR), hMainWnd, (DLGPROC)SelDirProc)!=IDOK) {
		return NULL;
	}
	else {
		return select_dir_path;
	}

	return NULL;
};


BOOL CALLBACK SelDirProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) { 
	char text[DIALOG_TEXTLEN];
	char newpath[LEN_FILENAME];
	char curpath[LEN_FILENAME];
	HWND listbox = GetDlgItem(hwndDlg, IDC_DIRLIST);
	int i, p, p1;

	switch (message) { 
		case WM_INITDIALOG:
			/* set path text */
			SetDlgItemText_wa(hwndDlg, IDC_EDIT, select_dir_path);
			break;
        case WM_COMMAND:
            switch (LOWORD(wParam)) 
            { 
                case IDOK:
					GetDlgItemText_wa(hwndDlg, IDC_EDIT, select_dir_path, LEN_FILENAME);
                case IDCANCEL: 
                    EndDialog(hwndDlg, wParam); 
                    return TRUE;
					break;
				case IDC_DIRLIST:
		            switch (HIWORD(wParam)) {
						case LBN_DBLCLK: {
							i = SendMessage (listbox, LB_GETCURSEL, 0, 0);
							if (i < 0) return TRUE;
							SendMessage_GetText_wa (listbox, LB_GETTEXT, i, (LPARAM)text, DIALOG_TEXTLEN);
							GetDlgItemText_wa(hwndDlg, IDC_EDIT, curpath, LEN_FILENAME);
							d_printf ("selected curtext '%s' text '%s'", curpath, text);
							if (curpath[strlen(curpath)-1] == DIR_SEP) snprintf (newpath, LEN_FILENAME, "%s%s%c", curpath, text, DIR_SEP);
							else  snprintf (newpath, LEN_FILENAME, "%s%c%s%c", curpath, DIR_SEP, text, DIR_SEP);
	
							/* check for "." and for ".." */
							for (curpath[0] = 0, p = 0, i = 0, p1 = -1; i < strlen (newpath) && p < LEN_FILENAME; i++) {
								if (newpath[i] == DIR_SEP && newpath[i+1] == DIR_SEP) continue;
								if (newpath[i] == DIR_SEP && newpath[i+1] == '.' && newpath[i+2] == '.') {
									if (p1 >= 0) {
										p = p1;
										curpath[p] = 0;
									}
									i = i + 2;
									continue;
								}
								curpath[p++] = newpath[i];
								curpath[p] = 0;
								if (curpath[p-1] == DIR_SEP) p1 = p;
							}

							/* set path text */
							SetDlgItemText_wa(hwndDlg, IDC_EDIT, curpath);
							break;
                    	} 
					}
					break;

				case IDC_EDIT:
					switch (HIWORD(wParam)) {
						case EN_CHANGE: {
							GetDlgItemText_wa(hwndDlg, IDC_EDIT, newpath, LEN_FILENAME);
							select_dir_refresh (hwndDlg, newpath);
						}
						break;
					}
					break;
            }
            return TRUE;
    } 
    return FALSE; 
};
