/*
 *  WSoundPrefs - WMSound Server Preferences Program
 *
 * Copyright (c) 1998, 1999 Pascal Hofstee
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "WSoundPrefs.h"
#include "SoundEvents.h"

static char *eventkey[] = {
	"Startup",
	"Shutdown",
	"AppStart",
	"AppExit",
	"Maximize",
	"UnMaximize",
	"Iconify",
	"DeIconify",
	"Hide",
	"UnHide",
	"Shade",
	"UnShade",
	"Dock",
	"UnDock",
	"Kaboom",
	"UserDefined",
	NULL
};

extern proplist_t WMSoundDomain;

static char* expandSoundPath (WMWidget *w, void *data, char* file);
static char* getPathFromName (char *name);
static char* checkSoundPath(char* file);

void
changeSoundEvent(WMWidget *w, void *data)
{
	Panel	*panel = (Panel*)data;
	
	WMSetTextFieldText(panel->sndfileT, GetStringForKey(eventkey[WMGetPopUpButtonSelectedItem(w)]));
	
	switch (WMGetPopUpButtonSelectedItem(w)) {
		case 0:
			WMSetLabelText(panel->sndevntL, _("This sound will be played when "
						"WSoundServer is started."));
			break;
		case 1:
			WMSetLabelText(panel->sndevntL, _("This sound will be played when "
						"WSoundServer shuts down."));
			break;
		case 2:
			WMSetLabelText(panel->sndevntL, _("This sound will be played when "
						"a new application is started."));
			break;
		case 3:
			WMSetLabelText(panel->sndevntL, _("This sound will be played when "
						"an application is shut down."));
			break;
		case 4:
			WMSetLabelText(panel->sndevntL, _("This sound will be played when "
						"a window is maximized."));
			break;
		case 5:
			WMSetLabelText(panel->sndevntL, _("This sound will be played when "
						"a window is restored to it's "
						"original window size again."));
			break;
		case 6:
			WMSetLabelText(panel->sndevntL, _("This sound will be played when "
						"a window is iconified."));
			break;
		case 7:
			WMSetLabelText(panel->sndevntL, _("This sound will be played when "
						"a window is restored to a "
						"non-iconified state."));
			break;
		case 8:
			WMSetLabelText(panel->sndevntL, _("This sound will be played when "
						"an application is hidden behind it's "
						"application icon."));
			break;
		case 9:
			WMSetLabelText(panel->sndevntL, _("This sound will be played when "
						"an application is restored from "
						"underneath it's application icon."));
			break;
		case 10:
			WMSetLabelText(panel->sndevntL, _("This sound will be played when "
						"a window is reduced to a mere titlebar."));
			break;
		case 11:
			WMSetLabelText(panel->sndevntL, _("This sound will be played when "
						"a window is restored from a shaded state."));
			break;
		case 12:
			WMSetLabelText(panel->sndevntL, _("This sound will be played when "
						"an appicon is docked."));
			break;
		case 13:
			WMSetLabelText(panel->sndevntL, _("This sound will be played when "
						"an application icon is released."));
			break;
		case 14:
			WMSetLabelText(panel->sndevntL, _("This sound will be played when "
						"an application icon is destroyed."));
			break;
	}
}

void
changedSound(WMTextFieldDelegate *self, WMNotification *notif)
{
	Panel		*panel;
	WMTextField	*tPtr = (WMTextField*)WMGetNotificationObject(notif);

	panel = WMGetHangedData(tPtr);
	SetStringForKey(WMGetTextFieldText(tPtr), eventkey[WMGetPopUpButtonSelectedItem(panel->sndevntP)]);
}

void
changedDevice(WMTextFieldDelegate *self, WMNotification *notif)
{
	Panel		*panel;
	WMTextField	*tPtr = (WMTextField*)WMGetNotificationObject(notif);

	panel = WMGetHangedData(tPtr);
	SetStringForKey(WMGetTextFieldText(tPtr), "Device");
}

void
playClick(WMWidget *w, void *data)
{
	Panel	*panel = (Panel*)data;
	char	*text, *soundfile;
	
	text = WMGetTextFieldText(panel->sndfileT);
	
	soundfile = expandSoundPath(w, data, text);
	if ((SPlaySound(soundfile) == -1)) {
		if (SErrorCode == SERR_NOSERVER) {
			if (!WMSoundDBLoaded)
				SLoadConfig();
			
			if (SCoreSound(soundfile) == -1)
				swarning(SMessageForError(SErrorCode));

			WMSoundDBLoaded = False;
			PLRelease(WMSoundDB);
		}
		else
			swarning(SMessageForError(SErrorCode));
	}

	free(soundfile);
}

void
clearClick(WMWidget *w, void *data)
{
	Panel	*panel = (Panel*)data;
	
	WMSetTextFieldText(panel->sndfileT, "None");
	SetStringForKey("None", eventkey[WMGetPopUpButtonSelectedItem(panel->sndevntP)]);
}

void
browseClick(WMWidget *w, void *data)
{
	Panel		*panel = (Panel*)data;
	WMOpenPanel	*browseP;
	char		path[PATH_MAX] = "\0";
	char		*spath = NULL;
	
	WMSetButtonEnabled(panel->sndbrowseB, NO);
	WMSetButtonEnabled(panel->sndsetloadB, NO);
	WMSetButtonEnabled(panel->sndsetsaveB, NO);
	
	if ((strcmp(panel->lastBrowseDir,"\0") == 0)) {
		strcpy(path, wexpandpath("~/GNUstep/Library/WindowMaker/Sounds"));
		spath = wmalloc(strlen(path)+2);
		strcpy(spath, path);
	}
	else {
		spath = wmalloc(strlen(panel->lastBrowseDir)+2);
		strcpy(spath, panel->lastBrowseDir);
	}
	
	browseP = WMGetOpenPanel(WMWidgetScreen(w));
	WMSetFilePanelCanChooseDirectories(browseP, NO);
	WMSetFilePanelCanChooseFiles(browseP, YES);
	if (WMRunModalFilePanelForDirectory(browseP, panel->win, spath , NULL, NULL)) {
		char *filename;
		filename = WMGetFilePanelFileName(browseP);
		
		strcpy(panel->lastBrowseDir,(getPathFromName(filename)));
		WMSetTextFieldText(panel->sndfileT,checkSoundPath(filename));
		SetStringForKey(WMGetTextFieldText(panel->sndfileT), eventkey[WMGetPopUpButtonSelectedItem(panel->sndevntP)]);
		free(filename);
	}
	WMFreeFilePanel(browseP);

	WMSetButtonEnabled(panel->sndbrowseB, YES);
	WMSetButtonEnabled(panel->sndsetloadB, YES);
	WMSetButtonEnabled(panel->sndsetsaveB, YES);
	free(spath);
}

void
loadClick(WMWidget *w, void *data)
{
	Panel		*panel = (Panel*)data;
	WMOpenPanel	*loadP;
	proplist_t	newset;
	char		path[PATH_MAX] = "\0";
	char		*spath = NULL;
	
	WMSetButtonEnabled(panel->sndsetloadB, NO);
	WMSetButtonEnabled(panel->sndbrowseB, NO);
	WMSetButtonEnabled(panel->sndsetsaveB, NO);
	
	if ((strcmp(panel->lastLoadDir,"\0") == 0)) {
		strcpy(path, wexpandpath("~/GNUstep/Library/WindowMaker/SoundSets"));
		spath = wmalloc(strlen(path)+2);
		strcpy(spath, path);
	}
	else {
		spath = wmalloc(strlen(panel->lastLoadDir)+2);
		strcpy(spath, panel->lastLoadDir);
	}
	
	loadP = WMGetOpenPanel(WMWidgetScreen(w));
	WMSetFilePanelCanChooseDirectories(loadP, NO);
	WMSetFilePanelCanChooseFiles(loadP, YES);
	if (WMRunModalFilePanelForDirectory(loadP, panel->win, spath , NULL, NULL)) {
		char *filename;
		filename = WMGetFilePanelFileName(loadP);
		
		strcpy(panel->lastLoadDir,(getPathFromName(filename)));
		newset = PLGetProplistWithPath(filename);
		
		if(!newset)
			WMRunAlertPanel(WMWidgetScreen(w), panel->win, _("Error"),
					_("Could not load specified SoundSet"), _("OK"), NULL, NULL);
		else {
			PLMergeDictionaries(WMSoundDomain,newset);
			WMSetTextFieldText(panel->sndfileT, GetStringForKey(eventkey[WMGetPopUpButtonSelectedItem(panel->sndevntP)]));
		}
		PLRelease(newset);
		free(filename);
	}
	WMFreeFilePanel(loadP);
	
	WMSetButtonEnabled(panel->sndsetloadB, YES);
	WMSetButtonEnabled(panel->sndbrowseB, YES);
	WMSetButtonEnabled(panel->sndsetsaveB, YES);
	
	free(spath);
}

void
saveClick(WMWidget *w, void *data)
{
	Panel		*panel = (Panel*)data;
	WMSavePanel	*saveP;
	proplist_t	newset, key, val;
	char		path[PATH_MAX] = "\0";
	char		*spath = NULL;
	FILE		*file;
	int		i;
	
	WMSetButtonEnabled(panel->sndbrowseB, NO);
	WMSetButtonEnabled(panel->sndsetloadB, NO);
	WMSetButtonEnabled(panel->sndsetsaveB, NO);
	
	if ((strcmp(panel->lastSaveDir,"\0") == 0)) {
		strcpy(path, wexpandpath("~/GNUstep/Library/WindowMaker/SoundSets"));
		spath = wmalloc(strlen(path)+2);
		strcpy(spath, path);
	}
	else {
		spath = wmalloc(strlen(panel->lastSaveDir)+2);
		strcpy(spath, panel->lastSaveDir);
	}
	
	saveP = WMGetSavePanel(WMWidgetScreen(w));
	WMSetFilePanelCanChooseDirectories(saveP, NO);
	WMSetFilePanelCanChooseFiles(saveP, YES);
	if (WMRunModalFilePanelForDirectory(saveP, panel->win, spath , NULL, NULL)) {
		char *filename = NULL;
		filename = WMGetFilePanelFileName(saveP);
		strcpy(panel->lastSaveDir,(getPathFromName(filename)));
		
		file = fopen (filename, "w+");
		if (file) {
			newset = PLMakeDictionaryFromEntries(NULL,NULL,NULL);
			
			for(i=0;eventkey[i]!="UserDefined";i++) {
				key = PLMakeString(eventkey[i]);
				val = PLGetDictionaryEntry(WMSoundDomain,key);
				if(val) PLInsertDictionaryEntry(newset,key,val);
			}
			PLRelease(key);
			
			fprintf (file, PLGetDescriptionIndent(newset,0));
			PLRelease(newset);
			fclose (file);
		}
		else
			WMRunAlertPanel(WMWidgetScreen(w), panel->win, _("Error"),
					_("Could not save SoundSet"), _("OK"), NULL, NULL);
		
		free(filename);
	}
	WMFreeFilePanel(saveP);
	
	WMSetButtonEnabled(panel->sndbrowseB, YES);
	WMSetButtonEnabled(panel->sndsetloadB, YES);
	WMSetButtonEnabled(panel->sndsetsaveB, YES);
	free(spath);
}






static char*
expandSoundPath (WMWidget *w, void *data, char* file)
{
	Panel *panel = (Panel*)data;
	proplist_t array, val;
	int nr_elem;
	int i = 0;
	char *path;
	char *tmp;
	
	assert(file!=NULL);
	
	if (strncmp(file, "/", 1) == 0) {
		return wstrdup(file);
	}
	
	array = GetObjectForKey("SoundPath");
	nr_elem = PLGetNumberOfElements(array);
	
	while (i < nr_elem) {
		val = PLGetArrayElement(array, i);
		path = wexpandpath(PLGetString(val));
		
		if ((path+strlen(path)-1) != "/") {
			tmp = wstrappend(path, "/");
			if (path)
				free(path);
			path = tmp;
		}
		tmp = wstrappend(path, file);
		if (path)
			free(path);
		path = tmp;
		
		if (access(path, F_OK) == 0) {
#ifdef DEBUG
			fprintf(stderr, "%s \t Found !\n", path);
#endif
			return path;
		}
#ifdef DEBUG
		fprintf(stderr, "%s \t Not Found!\n", path);
#endif
		free(path);
		i++;
	}
#ifdef DEBUG
	fprintf(stderr,"Tough Luck ... couldn't find specified sound.\n");
#endif
	WMRunAlertPanel(WMWidgetScreen(w), panel->win, _("Error"),
			_("Unable to locate specified soundfile.\n"
				"It either does not exist or is not accessible for the current user."), _("OK"), NULL, NULL);
	return wstrdup(file);
}

static char*
getPathFromName(char *name)
{
	int size;
	char result[PATH_MAX];
	
	assert(name != NULL);
	
	size = strlen(name);
	
	while (size > 1 && name[size-1] != '/')
		size--;
	
	return strncpy(result, name, size);
}

static char*
checkSoundPath(char* file)
{
	proplist_t	array, val;
	int		nr_elem;
	int		i = 0;
	char		*path;
	char		*tmp;
	
	assert(file!=NULL);
	
	array = GetObjectForKey("SoundPath");
	nr_elem = PLGetNumberOfElements(array);
	
	while (i < nr_elem) {
		val = PLGetArrayElement(array, i);
		path = wexpandpath(PLGetString(val));
		
		if ((path+strlen(path)-1) != "/") {
			tmp = wstrappend(path, "/");
			if (path)
				free(path);
			path = tmp;
		}
		
		if ((strncmp(path, file, strlen(path)-1)) == 0) {
			strcpy(file, file+strlen(path));
			break;
		}
		i++;
	}
	return file;
}

