/* copyright 	Maher Awamy <muhri@muhri.net>		*
 *		Charlie Schmidt <ishamael@themes.org>	*
 *							*
 *  released under the GPL				*/


/* SkipStone PromptService */

#include "mozilla-config.h"

#include "nsIUnicodeEncoder.h"
#include "nsIUnicodeDecoder.h"
#include "nsIPlatformCharset.h"
#include "nsICharsetConverterManager.h"

#include "PromptService.h"
#include "nsCOMPtr.h"
#include "nsIPromptService.h"
#include "nsIFactory.h"
#include "nsString.h"
#include "nsIWindowWatcher.h"
#include "nsIServiceManager.h"
#include "nsIWebBrowserChrome.h"
#include "nsIEmbeddingSiteWindow.h"
#include "SkipStonePrompter.h"
#include "debug.h"
#include "intl.h"


typedef struct
{
   gint buttonPressed;
   gboolean hasCheckValue;
   gboolean checkValue;
   GtkWidget *checkButton;
   GtkWidget *dialog;
}
buttonInfo;


static char *mozilla_unicode_to_locale (const PRUnichar *uniStr);
static void add_to_box(GtkWidget *box, gchar *string, gint data, buttonInfo *bi);
static void set_prompt_button(GtkWidget *button, buttonInfo *bi);


class CPromptService: public nsIPromptService
{
public:
			CPromptService();
  virtual	~CPromptService();

  NS_DECL_ISUPPORTS
  NS_DECL_NSIPROMPTSERVICE
  

};



NS_IMPL_ISUPPORTS1(CPromptService, nsIPromptService)

CPromptService::CPromptService()
{
	NS_INIT_ISUPPORTS();
}

CPromptService::~CPromptService()
{
}



NS_IMETHODIMP CPromptService::Alert(nsIDOMWindow *parent, const PRUnichar *aDialogTitle,
                                    const PRUnichar *aText)
{    
     D_ENTER;
     SkipStonePrompter prompter;
     prompter.SetTitle(aDialogTitle);
     prompter.SetMessageText(aText);
     prompter.Create(SkipStonePrompter::TYPE_ALERT);
     prompter.Run();
     D_RETURN_ ( NS_OK );
}

NS_IMETHODIMP CPromptService::AlertCheck(nsIDOMWindow *parent, const PRUnichar *aDialogTitle,
                                         const PRUnichar *aText,
                                         const PRUnichar *aCheckMsg, PRBool *aCheckValue)
{
     D_ENTER;
     SkipStonePrompter prompter;
     prompter.SetTitle(aDialogTitle);
     prompter.SetMessageText(aText);
     prompter.SetCheckMessage(aCheckMsg);
     prompter.SetCheckValue(*aCheckValue);
     prompter.Create(SkipStonePrompter::TYPE_ALERT_CHECK);
     prompter.Run();
     prompter.GetCheckValue(aCheckValue);
     D_RETURN_ ( NS_OK );
}

NS_IMETHODIMP CPromptService::Confirm(nsIDOMWindow *parent, const PRUnichar *aDialogTitle,
                                      const PRUnichar *aText,
                                      PRBool *_retval)
{
     D_ENTER;
     SkipStonePrompter prompter;
     prompter.SetTitle(aDialogTitle);
     prompter.SetMessageText(aText);
     prompter.Create(SkipStonePrompter::TYPE_CONFIRM);
     prompter.Run();
     prompter.GetConfirmValue(_retval);
     D_RETURN_ ( NS_OK );
}

NS_IMETHODIMP CPromptService::ConfirmCheck(nsIDOMWindow *parent, const PRUnichar *aDialogTitle,
                                           const PRUnichar *aText,
                                           const PRUnichar *aCheckMsg, PRBool *aCheckValue,
                                           PRBool *_retval)
{
     D_ENTER;
     SkipStonePrompter prompter;
     prompter.SetTitle(aDialogTitle);
     prompter.SetMessageText(aText);
     prompter.SetCheckMessage(aCheckMsg);
     prompter.SetCheckValue(*aCheckValue);
     prompter.Create(SkipStonePrompter::TYPE_CONFIRM);
     prompter.Run();
     prompter.GetConfirmValue(_retval);
     if (*_retval)
       	prompter.GetCheckValue(aCheckValue);
     D_RETURN_ ( NS_OK );
}

static void add_to_box(GtkWidget *vbox, gchar *string, gint data, buttonInfo *bi)
{
	GtkWidget *button = gtk_button_new_with_label(string);
	gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 1);
	gtk_widget_show(button);
	gtk_object_set_data(GTK_OBJECT(button), "number", GINT_TO_POINTER(data));
	gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(set_prompt_button), bi);
}

static void set_prompt_button(GtkWidget *button, buttonInfo *bi)
{

	bi->buttonPressed = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(button), "number"));
	if (bi->hasCheckValue)
	{
		bi->checkValue = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(bi->checkButton));
	}
   
	gtk_grab_remove(bi->dialog);
	gtk_widget_destroy(bi->dialog);
}



NS_IMETHODIMP CPromptService::ConfirmEx(nsIDOMWindow *parent, 
					const PRUnichar *aDialogTitle,
                                        const PRUnichar *aText,
                                        PRUint32 buttonFlags, 
					const PRUnichar *button0Title,
                                        const PRUnichar *button1Title,
					const PRUnichar *button2Title,
					const PRUnichar *checkMsg,
					PRBool *checkValue,
                                        PRInt32 *buttonPressed)
{

	D_ENTER;

	GtkWidget *dialog, *label, *checkButton, *vbox, *box;
	gchar *title=NULL;
	gint i=0;
	buttonInfo *bi=NULL;
        
	bi=g_new0(buttonInfo, 1);
	bi->buttonPressed=-1;
	dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	bi->dialog=dialog;
	vbox = gtk_vbox_new(FALSE, 0);
	gtk_container_add(GTK_CONTAINER(dialog), vbox);
	title = mozilla_unicode_to_locale(aDialogTitle);
	gtk_window_set_title(GTK_WINDOW(dialog), title);
	g_free(title);
	title = mozilla_unicode_to_locale(aText);
	label = gtk_label_new(title);
	g_free(title);
	gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
	title = mozilla_unicode_to_locale(checkMsg);
	checkButton = gtk_check_button_new_with_label(title);
	g_free(title);
        bi->checkButton = checkButton;
	gtk_box_pack_start(GTK_BOX(vbox), checkButton, FALSE, FALSE, 0);
	box = vbox;
	vbox = gtk_hbox_new(FALSE, 0);
	for (i = 0; i < 4; i++)
	{
	
		switch (buttonFlags & 0xff)
		{
	     
			case BUTTON_TITLE_OK:
				add_to_box(vbox, _("Ok"), i, bi);
				break;
			case BUTTON_TITLE_CANCEL:
				add_to_box(vbox, _("Cancel"), i, bi);
				break;
			case BUTTON_TITLE_YES:
				add_to_box(vbox, _("Yes"), i, bi);
				break;
			case BUTTON_TITLE_NO:
				add_to_box(vbox, _("No"), i , bi);
				break;
			case BUTTON_TITLE_SAVE:
				add_to_box(vbox, "Save", i , bi);
				break;
			case BUTTON_TITLE_REVERT:
				add_to_box(vbox, _("Revert"), i , bi);
				break;
			case BUTTON_TITLE_DONT_SAVE:
				add_to_box(vbox, _("Don't Save"), i, bi);
				break;
			case BUTTON_TITLE_IS_STRING:
				{
					gchar *tmpstr=NULL;
					if (i==0)
						tmpstr = mozilla_unicode_to_locale (button0Title);
					else if (i==1)
						tmpstr = mozilla_unicode_to_locale (button1Title);
					else if (i==2)
						tmpstr = mozilla_unicode_to_locale (button2Title);
					else
						break;
					add_to_box(vbox, tmpstr, i, bi);
					g_free(tmpstr);
				}
				break;
			default:
				break;
		}	     
		buttonFlags >>= 8;
	}
	gtk_box_pack_start(GTK_BOX(box), vbox, FALSE, FALSE, 0);

	if (checkValue == NULL) {
		bi->hasCheckValue=FALSE;
		bi->checkValue=FALSE;
	} else {     
		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkButton), *checkValue);
		bi->hasCheckValue=TRUE;
		bi->checkValue = *checkValue;
	}     	        
   
	if (checkValue != NULL) gtk_widget_show(checkButton);
	gtk_widget_show(vbox);
	gtk_widget_show(box);
	gtk_widget_show(label);
	gtk_widget_show(dialog);
	gtk_signal_connect(GTK_OBJECT(dialog), "destroy", gtk_main_quit, NULL);
	gtk_grab_add(dialog);
	gtk_main();
	
	if (bi->buttonPressed != -1) {
		*buttonPressed = bi->buttonPressed;
		if (checkValue != NULL) *checkValue = bi->checkValue;
	}
   
	/* bye bye info struct */
	g_free(bi);
	D_RETURN_ ( NS_OK );
}


NS_IMETHODIMP CPromptService::Prompt(nsIDOMWindow *parent, const PRUnichar *aDialogTitle,
                                     const PRUnichar *aText, PRUnichar **result,
                                     const PRUnichar *aCheckMsg, PRBool *aCheckValue,
                                     PRBool *_retval)
{
     	D_ENTER;
     	SkipStonePrompter prompter;
     	prompter.SetTitle(aDialogTitle);
     	prompter.SetMessageText(aText);
     	if (result && *result)
       		prompter.SetTextValue(*result);
     	if (aCheckValue) {
	     	prompter.SetCheckValue(*aCheckValue);
	     	if (aCheckMsg)
	       		prompter.SetCheckMessage(aCheckMsg);
	     	else
	       		prompter.SetCheckMessage(NS_LITERAL_STRING("Save This Value").get());
	}
     	prompter.Create(SkipStonePrompter::TYPE_PROMPT);
     	prompter.Run();
     	prompter.GetConfirmValue(_retval);
     	if (*_retval) {
	     	if (result && *result) {
		     	nsMemory::Free(*result);
		     	*result = nsnull;
		}
	     	prompter.GetTextValue(result);
	     	if (aCheckValue)
	       		prompter.GetCheckValue(aCheckValue);
	}
     	D_RETURN_ (  NS_OK );
}

NS_IMETHODIMP CPromptService::PromptUsernameAndPassword(nsIDOMWindow *parent, const PRUnichar *aDialogTitle,
                                                        const PRUnichar *aText,
                                                        PRUnichar **aUser, PRUnichar **aPwd,
                                                        const PRUnichar *aCheckMsg, PRBool *aCheckValue,
                                                        PRBool *_retval)
{
     	D_ENTER;
     	SkipStonePrompter prompter;
     	prompter.SetTitle(aDialogTitle);
     	prompter.SetMessageText(aText);
     	if (aUser && *aUser)
       		prompter.SetUser(*aUser);
     	if (aPwd && *aPwd)
       		prompter.SetPassword(*aPwd);
     	if (aCheckValue) {
	     	prompter.SetCheckValue(*aCheckValue);
	     	if (aCheckMsg)
	       		prompter.SetCheckMessage(aCheckMsg);
	     	else
	       		prompter.SetCheckMessage(NS_LITERAL_STRING("Save These Values").get());
	}
     	prompter.Create(SkipStonePrompter::TYPE_PROMPT_USER_PASS);
     	prompter.Run();
     	prompter.GetConfirmValue(_retval);
     	if (*_retval) {
	     	if (aUser && *aUser) {
		     	nsMemory::Free(*aUser);
		     	*aUser = nsnull;
		}
	     	prompter.GetUser(aUser);
	     	if (aPwd && *aPwd) {
		     	nsMemory::Free(*aPwd);
		     	*aPwd = nsnull;
		}
	     	prompter.GetPassword(aPwd);
	     	if (aCheckValue)
	       		prompter.GetCheckValue(aCheckValue);
	}

       	D_RETURN_ ( NS_OK );
}


NS_IMETHODIMP CPromptService::PromptPassword(nsIDOMWindow *parent, const PRUnichar *aDialogTitle,
                                             const PRUnichar *aText,
                                             PRUnichar **aPwd,
                                             const PRUnichar *aCheckMsg, PRBool *aCheckValue,
                                             PRBool *_retval)
{
     	D_ENTER;
     	SkipStonePrompter prompter;
     	prompter.SetTitle(aDialogTitle);
     	prompter.SetMessageText(aText);
     	if (aPwd && *aPwd)
       		prompter.SetPassword(*aPwd);
     	if (aCheckValue) {
	     	prompter.SetCheckValue(*aCheckValue);
	     	if (aCheckMsg)
	       		prompter.SetCheckMessage(aCheckMsg);
	     	else
	       		prompter.SetCheckMessage(NS_LITERAL_STRING("Save Password").get());
	}
     	prompter.Create(SkipStonePrompter::TYPE_PROMPT_PASS);
     	prompter.Run();
     	prompter.GetConfirmValue(_retval);
     	if (*_retval) {
	     	if (aPwd && *aPwd) {
		     	nsMemory::Free(*aPwd);
		     	*aPwd = nsnull;
		}
	     	prompter.GetPassword(aPwd);
	     	if (aCheckValue)
	       		prompter.GetCheckValue(aCheckValue);
	}
     	D_RETURN_ ( NS_OK );
}

NS_IMETHODIMP CPromptService::Select(nsIDOMWindow *parent, 
				     const PRUnichar *aDialogTitle,
                                     const PRUnichar *aText, 
				     PRUint32 count,
                                     const PRUnichar **selectList, 
				     PRInt32 *outSelection,
                                     PRBool *_retval)
{

     D_ENTER;
     SkipStonePrompter Prompter;
     Prompter.SetTitle(aDialogTitle);
     Prompter.SetMessageText(aText);
     Prompter.Create(SkipStonePrompter::TYPE_CONFIRM);
     Prompter.Run();
     Prompter.GetConfirmValue(_retval);
     D_RETURN_ ( NS_OK );
}
 
//*****************************************************************************
// CPromptServiceFactory
//*****************************************************************************   

class CPromptServiceFactory : public nsIFactory
{
public:
  NS_DECL_ISUPPORTS
  NS_DECL_NSIFACTORY

  CPromptServiceFactory();
  virtual ~CPromptServiceFactory();
};

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

NS_IMPL_ISUPPORTS1(CPromptServiceFactory, nsIFactory)

CPromptServiceFactory::CPromptServiceFactory()
{
  NS_INIT_ISUPPORTS();
}

CPromptServiceFactory::~CPromptServiceFactory()
{
}

NS_IMETHODIMP CPromptServiceFactory::CreateInstance(nsISupports *aOuter, const nsIID & aIID, void **aResult)
{
  D_ENTER;
  NS_ENSURE_ARG_POINTER(aResult);
  
  *aResult = NULL;  
  CPromptService *inst = new CPromptService;    
  if (!inst)
    D_RETURN_ (  NS_ERROR_OUT_OF_MEMORY );
    
  nsresult rv = inst->QueryInterface(aIID, aResult);
  if (rv != NS_OK) {  
    // We didn't get the right interface, so clean up  
    delete inst;  
  }  
    
  D_RETURN_ ( rv );
}

NS_IMETHODIMP CPromptServiceFactory::LockFactory(PRBool lock)
{
     D_ENTER;
     D_RETURN_ ( NS_OK );
}

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

nsresult NS_NewPromptServiceFactory(nsIFactory** aFactory)
{
  D_ENTER;
  NS_ENSURE_ARG_POINTER(aFactory);
  *aFactory = nsnull;
  
  CPromptServiceFactory *result = new CPromptServiceFactory;
  if (!result)
    D_RETURN_ (  NS_ERROR_OUT_OF_MEMORY );
    
  NS_ADDREF(result);
  *aFactory = result;
  
  D_RETURN_ (  NS_OK );
}



static char *mozilla_unicode_to_locale (const PRUnichar *uniStr)
{

     
      if (uniStr == NULL)
       {
	                    D_RETURN_ ( NULL );
       }
     
             nsAutoString autoStr ( uniStr );
     
     #ifdef MOZ_WIDGET_GTK
             gchar* locStr = ToNewCString(autoStr);
     #endif
     
     #ifdef MOZ_WIDGET_GTK2
             gchar* locStr = ToNewUTF8String(autoStr);
     #endif
     
             D_RETURN_ ( locStr );
     
     

}
