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


/* lousy implementation based on the old EmbedPrompter code by Blizzard*/

#include "SkipStonePrompter.h"
#include "intl.h"
#include "debug.h"

static gboolean toplevel_delete_cb(GtkWidget *aWidget, GdkEventAny *aEvent,
		   SkipStonePrompter *aPrompter);
static gboolean ok_clicked_cb(GtkButton *button, SkipStonePrompter *aPrompter);
static void on_pass_activate(GtkEntry *entry, SkipStonePrompter *aPrompter);
static gboolean cancel_clicked_cb(GtkButton *button, SkipStonePrompter *aPrompter);
static GtkWidget *ok = nsnull;

SkipStonePrompter::SkipStonePrompter(void)
{
  mCheckValue    = PR_FALSE;
  mConfirmResult = PR_FALSE;

  mWindow        = nsnull;
  mUserField     = nsnull;
  mPassField     = nsnull;
  mTextField     = nsnull;
  mCheckBox      = nsnull;
}

SkipStonePrompter::~SkipStonePrompter(void)
{
}

nsresult
SkipStonePrompter::Create(PromptType aType)
{
	D_ENTER;
     	nsresult rv = NS_OK;

     	int includeCheckFlag = 0;

     	switch (aType) {
	 	case TYPE_PROMPT_USER_PASS:
	     		if (mCheckMessage.Length())
	       			includeCheckFlag = SkipStonePrompter::INCLUDE_CHECKBOX;
	     		CreatePasswordPrompter(SkipStonePrompter::INCLUDE_USERNAME | includeCheckFlag);
	     		break;
	 	case TYPE_PROMPT_PASS:
	     		if (mCheckMessage.Length())
			      includeCheckFlag = SkipStonePrompter::INCLUDE_CHECKBOX;
	     		CreatePasswordPrompter(includeCheckFlag);
	     		break;
	 	case TYPE_ALERT:
	     		CreateAlertPrompter(0);
	     		break;
	 	case TYPE_CONFIRM:
	     		CreateAlertPrompter(SkipStonePrompter::INCLUDE_CANCEL);
	     		break;
	 	case TYPE_CONFIRM_CHECK:
	     		CreateAlertPrompter(SkipStonePrompter::INCLUDE_CANCEL |
					    SkipStonePrompter::INCLUDE_CHECKBOX);
	     	break;
	 	case TYPE_ALERT_CHECK:
	     		CreateAlertPrompter(SkipStonePrompter::INCLUDE_CHECKBOX);
	     		break;
	 	case TYPE_PROMPT:
	     		if (mCheckMessage.Length())
	       			includeCheckFlag = SkipStonePrompter::INCLUDE_CHECKBOX;
	     			CreateAlertPrompter(SkipStonePrompter::INCLUDE_CANCEL |
						    SkipStonePrompter::INCLUDE_TEXTFIELD |
						    includeCheckFlag);
	     		break;
	 	default:
	                g_print("Returning NOT IMPLEMENTED\n");
	     		rv = NS_ERROR_NOT_IMPLEMENTED;
	     		break;
	}
     	D_RETURN_ ( rv );
}

void
SkipStonePrompter::SetTitle(const PRUnichar *aTitle)
{
     	D_ENTER;
     	mTitle.AssignWithConversion(aTitle);
     	D_RETURN;
}

void
SkipStonePrompter::SetTextValue(const PRUnichar *aTextValue)
{
     	D_ENTER;
     	mTextValue.AppendWithConversion(aTextValue);
     	D_RETURN;
}

void
SkipStonePrompter::SetCheckMessage(const PRUnichar *aMessage)
{
     	D_ENTER;
     	mCheckMessage.AppendWithConversion(aMessage);
     	D_RETURN;
}

void
SkipStonePrompter::SetMessageText(const PRUnichar *aMessageText)
{
     	D_ENTER;
     	nsAutoString autoStr (aMessageText);
        mMessageText = ToNewUTF8String(autoStr);
     	D_RETURN;
}

void
SkipStonePrompter::SetUser(const PRUnichar *aUser)
{
     	D_ENTER;
     	mUser.AppendWithConversion(aUser);
     	D_RETURN;
}

void
SkipStonePrompter::SetPassword(const PRUnichar *aPass)
{
     	D_ENTER;
     	mPass.AppendWithConversion(aPass);
     	D_RETURN;
}

void
SkipStonePrompter::SetCheckValue(const PRBool aValue)
{
     	D_ENTER;
     	mCheckValue = aValue;
     	D_RETURN;
}

void
SkipStonePrompter::GetCheckValue(PRBool *aValue)
{
     	D_ENTER;
     	*aValue = mCheckValue;
     	D_RETURN;
}

void
SkipStonePrompter::GetConfirmValue(PRBool *aConfirmValue)
{
     D_ENTER;
     *aConfirmValue = mConfirmResult;
     D_RETURN;  
}
 
void
SkipStonePrompter::GetTextValue(PRUnichar **aTextValue)
{
     	D_ENTER;
     	*aTextValue = ToNewUnicode(mTextValue);
     	D_RETURN;
}

void
SkipStonePrompter::GetUser(PRUnichar **aUser)
{
     	D_ENTER;
     	*aUser =ToNewUnicode(mUser);
     	D_RETURN;
}

void
SkipStonePrompter::GetPassword(PRUnichar **aPass)
{
     	D_ENTER;
     	*aPass = ToNewUnicode(mPass);
     	D_RETURN;
}

void
SkipStonePrompter::Run(void)
{
     	D_ENTER;
     	gtk_widget_show_all(mWindow);
     	
     	if (mUserField) {
	     	gtk_widget_grab_focus(mUserField);
	} else {
	     	if (ok) gtk_widget_grab_focus(ok);
	}
	       		
     	gtk_grab_add(mWindow);
     	gtk_main();
     	D_RETURN;
}

void
SkipStonePrompter::UserCancel(void)
{
     	D_ENTER;
     	// someone pressed cancel or else they closed the window which is
     	// the same as a cancel.
     	mConfirmResult = PR_FALSE;

     	gtk_grab_remove(mWindow);
     	gtk_main_quit();

     	// destroy all of our widgets
     	gtk_widget_destroy(mWindow);

     	mWindow = nsnull;
     	mUserField = nsnull;
     	mPassField = nsnull;
     	mTextField = nsnull;
     	mCheckBox = nsnull;
	ok = nsnull;
     	D_RETURN;
}

void
SkipStonePrompter::UserOK(void)
{
     	D_ENTER;
     	// someone pressed OK
     	mConfirmResult = PR_TRUE;

     	// save all of the data
     	if (mUserField) {
	     	gchar *user;
	     	user = gtk_editable_get_chars(GTK_EDITABLE(mUserField), 0, -1);
	     	mUser.Assign(user);
	     	g_free(user);
	}

     	if (mPassField) {
	     	gchar *pass;
	     	pass = gtk_editable_get_chars(GTK_EDITABLE(mPassField), 0, -1);
	     	mPass.Assign(pass);
	     	g_free(pass);
	}

     	if (mCheckBox)
       		mCheckValue = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(mCheckBox));
     	
     	if (mTextField) {
	     	gchar *text;
	     	text = gtk_editable_get_chars(GTK_EDITABLE(mTextField), 0, -1);
	     	mTextValue.Assign(text);
	     	g_free(text);
	}
  
     	gtk_grab_remove(mWindow);
     	gtk_main_quit();

     	// destroy all of our widgets
     	gtk_widget_destroy(mWindow);

     	mWindow = nsnull;
     	mUserField = nsnull;
     	mPassField = nsnull;
     	mTextField = nsnull;
     	mCheckBox = nsnull;
     	ok = nsnull;
     	D_RETURN;
}



void
SkipStonePrompter::CreatePasswordPrompter(int aFlags)
{
	
     	D_ENTER;
     	mWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
     	gtk_window_set_position(GTK_WINDOW(mWindow), GTK_WIN_POS_MOUSE);
     	gtk_window_set_title(GTK_WINDOW(mWindow), _("SkipStone Prompt"));
     	GtkBox *topLevelVBox = GTK_BOX(gtk_vbox_new(FALSE, 3));

     	gtk_container_add(GTK_CONTAINER(mWindow),  GTK_WIDGET(topLevelVBox));     
     	gtk_container_set_border_width(GTK_CONTAINER(mWindow),4);

  	GtkWidget *msgLabel = gtk_label_new(mMessageText);

     	gtk_box_pack_start(topLevelVBox, msgLabel, FALSE, FALSE, 0);    

     	PRInt32 startPos;

     	if (aFlags & SkipStonePrompter::INCLUDE_USERNAME) {
	     	GtkWidget *userLabel = gtk_label_new(_("User Name"));
	     	gtk_box_pack_start(topLevelVBox, userLabel,FALSE,FALSE,0);
	     	// the username text area
	     	mUserField = gtk_entry_new();
	     	if (mUser.Length()) {
		     	startPos = 0;
		     	gtk_editable_insert_text(GTK_EDITABLE(mUserField),
						 mUser.get(), mUser.Length(),
						 &startPos);
		}
	     	gtk_box_pack_start(topLevelVBox,mUserField,FALSE,FALSE,0);


	}

     	// password label
     	GtkWidget *passLabel = gtk_label_new(_("Password"));
     	gtk_box_pack_start(topLevelVBox, passLabel, FALSE, FALSE, 0);
     	// password text field
     	mPassField = gtk_entry_new();
     	gtk_signal_connect(GTK_OBJECT(mPassField), "activate", GTK_SIGNAL_FUNC(on_pass_activate), this);
     	// it's a password field
     	gtk_entry_set_visibility(GTK_ENTRY(mPassField), FALSE);
     	if (mPass.Length()) {
	     	startPos = 0;
	     	gtk_editable_insert_text(GTK_EDITABLE(mPassField),
					 mPass.get(), mPass.Length(),
					 &startPos);
	}
     	// add it
     	gtk_box_pack_start(topLevelVBox,mPassField,FALSE,FALSE,0);
	

     	// password manager field
     	if (aFlags & SkipStonePrompter::INCLUDE_CHECKBOX) {
	     	// make it
	     	mCheckBox = gtk_check_button_new_with_label(mCheckMessage.get());
	     	// set its state
	     	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mCheckBox),mCheckValue);		
	     	gtk_box_pack_start(topLevelVBox,mCheckBox,FALSE,FALSE,0);
	}

     	// gtk button box for the OK and Cancel buttons
     	GtkButtonBox *buttonBox = GTK_BUTTON_BOX(gtk_hbutton_box_new());
     	gtk_button_box_set_layout(buttonBox, GTK_BUTTONBOX_SPREAD);
     	gtk_box_pack_start(topLevelVBox,GTK_WIDGET(buttonBox), FALSE, TRUE, 0);
	

     	// OK
     	GtkWidget *okButton = gtk_button_new_with_label(_("OK"));
     	ok = okButton;
     	gtk_box_pack_start(GTK_BOX(buttonBox),okButton,FALSE,TRUE,0);
     	// cancel
     	GtkWidget *cancelButton = gtk_button_new_with_label(_("Cancel"));
     	gtk_box_pack_start(GTK_BOX(buttonBox),cancelButton,FALSE,TRUE,0);
	  
     	// hook up signals
     	gtk_signal_connect(GTK_OBJECT(mWindow), "delete_event",
			   GTK_SIGNAL_FUNC(toplevel_delete_cb),
			   this);
  
     	gtk_signal_connect(GTK_OBJECT(okButton), "clicked",
			   GTK_SIGNAL_FUNC(ok_clicked_cb), this);
     	gtk_signal_connect(GTK_OBJECT(cancelButton), "clicked",
			   GTK_SIGNAL_FUNC(cancel_clicked_cb), this);
     	D_RETURN;
}

void
SkipStonePrompter::CreateAlertPrompter(int aFlags)
{
	D_ENTER;

     	mWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
     	gtk_window_set_position(GTK_WINDOW(mWindow), GTK_WIN_POS_MOUSE);
     	gtk_window_set_title(GTK_WINDOW(mWindow), _("SkipStone Prompt"));
     	GtkBox *topLevelVBox = GTK_BOX(gtk_vbox_new(FALSE, 3));
     	gtk_container_add(GTK_CONTAINER(mWindow), GTK_WIDGET(topLevelVBox));
     	gtk_container_set_border_width(GTK_CONTAINER(mWindow),4);
     	
     	// create our label
     	GtkWidget *label = gtk_label_new(mMessageText);

     	gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);     	
     	gtk_box_pack_start(topLevelVBox,label,TRUE,TRUE,0);

     	// text field
     	if (aFlags & SkipStonePrompter::INCLUDE_TEXTFIELD) {
	     	mTextField = gtk_entry_new();
	     	if (mTextValue.Length()) {
		     	int startPos = 0;
		     	gtk_editable_insert_text(GTK_EDITABLE(mTextField),
						 mTextValue.get(), mTextValue.Length(),
						 &startPos);
		}
	     	gtk_box_pack_start(topLevelVBox,mTextField,FALSE,FALSE,0);
	}

     	if (aFlags & SkipStonePrompter::INCLUDE_CHECKBOX) {
	     	// make it
	     	mCheckBox = gtk_check_button_new_with_label(mCheckMessage.get());
	     	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mCheckBox),mCheckValue);
	     	gtk_box_pack_start(topLevelVBox,mCheckBox,FALSE,FALSE,0);
	}


     	// gtk button box for the OK button
     	GtkButtonBox *buttonBox = GTK_BUTTON_BOX(gtk_hbutton_box_new());
     	gtk_button_box_set_layout(buttonBox, GTK_BUTTONBOX_SPREAD);
     	gtk_box_pack_start(topLevelVBox,GTK_WIDGET(buttonBox),FALSE,FALSE,0);

     	// OK
     	GtkWidget *okButton = gtk_button_new_with_label(_("OK"));
     	ok = okButton;
     	gtk_box_pack_start(GTK_BOX(buttonBox),okButton,FALSE,TRUE,0);
	
     	if (aFlags & SkipStonePrompter::INCLUDE_CANCEL) {
	     	// cancel
	     	GtkWidget *cancelButton = gtk_button_new_with_label(_("Cancel"));
	     	gtk_box_pack_start(GTK_BOX(buttonBox),cancelButton,FALSE,TRUE,0);		
	     	gtk_signal_connect(GTK_OBJECT(cancelButton), "clicked",
				   GTK_SIGNAL_FUNC(cancel_clicked_cb), this);
	}
  

     	// hook up signals
     	gtk_signal_connect(GTK_OBJECT(mWindow), "delete_event",
			   GTK_SIGNAL_FUNC(toplevel_delete_cb),
			   this);
     	gtk_signal_connect(GTK_OBJECT(okButton), "clicked",
			   GTK_SIGNAL_FUNC(ok_clicked_cb), this);
     	D_RETURN;
}

static gboolean toplevel_delete_cb(GtkWidget *aWidget, GdkEventAny *aEvent,
				   SkipStonePrompter *aPrompter)
{
     	D_ENTER;
     	aPrompter->UserCancel();
     	D_RETURN_ ( TRUE );
}

static void on_pass_activate(GtkEntry *entry, SkipStonePrompter *aPrompter)
{
     	D_ENTER;
     	aPrompter->UserOK();
     	D_RETURN;
}

static gboolean ok_clicked_cb(GtkButton *button, SkipStonePrompter *aPrompter)
{
     	D_ENTER;
     	aPrompter->UserOK();
     	D_RETURN_ ( TRUE );
}

static gboolean cancel_clicked_cb(GtkButton *button, SkipStonePrompter *aPrompter)
{
     	D_ENTER;
     	aPrompter->UserCancel();
     	D_RETURN_ ( TRUE );
}


