/**************************************************************

utils.h (C-Munipack project)
Helper functions
Copyright (C) 2008 David Motl, dmotl@volny.cz

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 MUNIWIN_UTILS_H
#define MUNIWIN_UTILS_H

#include <gtk/gtk.h>
#include <cmunipack.h>

// PI number 
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

// Constants
#define MAX_APERTURES		12
#define MAX_SELECTION		64
#define MAX_PROJECT_NAME	FILENAME_MAX-16
#define MAX_PROFILE_NAME	FILENAME_MAX-16
#define MAX_OBJECT_LEN		260
#define MAX_OBSERVER_LEN	260
#define MAX_LOCATION_LEN	260
#define JD_MIN				2299163.0
#define JD_MAX				1e7
#define JD_PREC				7			// Number of decimal places for JD */

// Return nearest integer number with limit checking
int RoundToInt(double x);

// Bound value to limits
double LimitValue(double value, double min, double max);
int LimitValue(int value, int min, int max);

// Compute minimum and maximum
bool ComputeMinMax(int count, const double *data, double *min, double *max);

// Get path to the directory with user configuration files
const char *get_user_config_dir(void);

// Get path to the directory with user data files
const char *get_user_data_dir(void);

// Get path to the directory with shared files
const char *get_share_dir(void);

// Get path to the icon file
char *get_icon_file(const gchar *icon);

// Get a button from dialog's action area by a response id
GtkWidget *get_dialog_widget_by_response(GtkDialog *pDlg, gint response_id);

// Set standard tooltips for standard dialog buttons
void gtk_dialog_widget_standard_tooltips(GtkDialog *pDlg);

// Set standard tooltips for file chooser dialog
void gtk_file_chooser_standard_tooltips(GtkFileChooser *pDlg);

// Set tooltip text to a button from dialog's action area 
void gtk_dialog_set_tooltip_by_response(GtkDialog *pDlg, gint response_id, const gchar *tooltip);

// Make directory tree
bool force_directory(const gchar *path);

// Open a file (file name is UTF-8 encoded)
FILE *open_file(const gchar *fpath, const gchar *mode);

// Copy a file (file name is UTF-8 encoded)
bool copy_file(const gchar *source, const gchar *target, bool fail_if_exists, GError **error);

// Copy all files in directory (file name is UTF-8 encoded)
bool copy_all_files(const gchar *source, const gchar *target, bool recursive, GError **error);

// Show message box with error message
void ShowError(GtkWindow *pParent, const char *message, bool play_sound = false);

// Show message box with warning message
void ShowWarning(GtkWindow *pParent, const char *message, bool play_sound = false);

// Show message box with information
void ShowInformation(GtkWindow *pParent, const char *message, bool play_sound = false);

// Show configuration message box
bool ShowConfirmation(GtkWindow *pParent, const char *message);

// Show configuration message box
GtkResponseType ShowYesNoCancel(GtkWindow *pParent, const char *message);


//
// Error reporting
// ---------------
//
void set_error(GError **error, int errcode);
void set_error(GError **error, const gchar *caption, int errcode = 0);
void set_error(GError **error, const gchar *caption, const gchar *filename, int errcode = 0);


//
// File system utilities
// ---------------------
//

// Test file or directory and ask for confirmation before replacing it
// If the file/directory does not exist, returns true immediately.
// Otherwise, shows a message and returns true if the user confirmed it.
bool ConfirmOverwrite(GtkWindow *pParent, const gchar *path);
bool ConfirmOverwriteDir(GtkWindow *pParent, const gchar *path);

// Add file extension 
// the extension is always added to the end of the path
gchar *AddFileExtension(const gchar *path, const gchar *ext);

// Remove file extension
// if path contains an extension it is removed. Otherwise returns copy of path.
gchar *StripFileExtension(const gchar *path);

// Set the file extension
// if the path contains an extension, it is replaced
// if the path does not contain an extension, it is added
gchar *SetFileExtension(const gchar *path, const gchar *ext);

// Get file extension. Returns pointer to newly allocated nul-terminaeted string 
// that contains file's extension (after the last period). Returns NULL if the 
// filename does not have an extension. The extension does not include the period.
gchar *GetFileExtension(const gchar *path);

// Check file extension
bool CheckFileExtension(const gchar *path, const gchar *ext);

// Check given string if it is valid file base name 
bool CheckFileBaseName(const gchar *filename);

// Compare two absolute UTF-8 paths, they can be NULL
int ComparePaths(const gchar *fpath1, const gchar *fpath2);

// Transform given path 
// patterns:
//	%d			- dir path including trailing separator
//	%n			- base file name without the extension (before last dot)
//	%e			- file extension (after last dot)
//	%%			- % character itself
// Returns newly allocated string
gchar *TransformPath(const gchar *path, const gchar *pattern);

//
// String utilities
// ----------------
//

// Case sensitive comparison or two UTF-8 strings, they can be NULL
int StrCmp0(const gchar *str1, const gchar *str2);

// Case insensitive comparison or two UTF-8 strings, they can be NULL
int StrCaseCmp0(const gchar *str1, const gchar *str2);

// Case sensitive substring search for two UTF-8 strings, they can be NULL
// If either str1 or str2 is NULL, the result is always NULL
const gchar *StrStr0(const gchar *str1, const gchar *str2);

// Case insensitive substring search for two UTF-8 strings, they can be NULL
// If either str1 or str2 is NULL, the result is always NULL
const gchar *StrCaseStr0(const gchar *str1, const gchar *str2);

// Case sensitive substring search in memory buffer
const gchar *MemStr(const gchar *buffer, const gchar *substr, gsize buflength);

// Quote a string if necessary (it contains a quote character or a field separator)
// Quotes inside a quoted string are replaced by two subsequent quotes
gchar *StrQuote(const gchar *str, gchar separator, gchar quotechar, bool quote_always);

// If the string is quoted (first non-ws character is quote), remove quotes
// Two subsequent quotes in a quoted string are replaced by a single quote
// If the string is not quoted, the function just removes trailing and leading spaces.
gchar *StrUnquote(const gchar *str, gchar quotechar);


//
// Date and time conversion
// ------------------------
//

// Convert Julian date to struct tm
bool jdtime(gdouble jd, struct tm *tm);

// Convert struct tm to Julian date
double timejd(const struct tm *tm);

//
// Combo box helper functions
// --------------------------
//

// Select item in the combo box using model's first column
void SelectItem(GtkComboBox *cb, int id);

// Get integer value from combo box first column
int SelectedItem(GtkComboBox *cb, int defValue = -1);

//
// Toolbar helper functions
// ------------------------
//

// Add a standard button
GtkToolItem *toolbar_new_button_from_stock(GtkWidget *toolbar, const gchar *stock_id, const gchar *tooltip);

// Add a custom button
GtkToolItem *toolbar_new_button(GtkWidget *toolbar, const gchar *label, const gchar *tooltip);

// Add a radio button
GtkToolItem *toolbar_new_radio_button(GtkWidget *toolbar, GtkToolItem *first_in_group, const gchar *label, const gchar *tooltip);

// Add a separator
GtkToolItem *toolbar_new_separator(GtkWidget *toolbar);

// Add a label
GtkWidget *toolbar_new_label(GtkWidget *toolbar, const gchar *caption);

// Add a combo box
GtkWidget *toolbar_new_combo(GtkWidget *toolbar, const gchar *tooltip);

// Add a text field
GtkWidget *toolbar_new_entry(GtkWidget *toolbar, const gchar *tooltip, bool editable = true, double align = 0);

// Add a combo box entry
GtkWidget *toolbar_new_combo_box_entry(GtkWidget *toolbar, const gchar *tooltip);

// Add a child toolbar
GtkWidget *toolbar_new_toolbar(GtkWidget *toolbar);

//
// File lock
//
class FileLock
{
public:
	// Constructor
	FileLock();

	// Destructor
	virtual ~FileLock();

	// Acquire lock
	// params:
	//	fpath - file to be locked, this is NOT the name of the special file
	//			that keeps the status of the lock
	bool Acquire(const gchar *fpath);

	// Release lock
	void Release(void);

private:
#ifdef _WIN32
	void *m_File;
#else
	int	m_File;
#endif
};


//
// Sorter
//
struct tSortItem
{
	union tSortValue {
		int i;
		double d;
		char *s;
		unsigned long ul;
	} value;
	int row;
};

enum tSortType
{
	SORT_TYPE_INT, SORT_TYPE_STRING, SORT_TYPE_DOUBLE, SORT_TYPE_ULONG
};

void SortItems(tSortItem *items, int length, tSortType type, GtkSortType sort_order);

#endif
