#include "addressbook.h"
#include <stdlib.h>
#include <gtk/gtkinvisible.h>
#include <message.h>


#define BOARD_WD	210
#define BOARD_HT	180

#define LAST_RECORD	-1
#define THIS_RECORD	0
#define NEXT_RECORD	+1


typedef struct _entry_rec
{
   gchar *label;
   gint size;
} _entry_rec, entry_rec;


static entry_rec entry_recs[] = {
	{"First name:", 99},
	{"Last name:", 99},
	{"Title:", 99},
	{"Company:", 99},
	{"Work:", 99},
	{"Home:", 99},
	{"Fax:", 99},
	{"Other:", 99},
	{"Email:", 99},
	{"Address:", 99},
	{"", 99}
};

static GtkWidget *item_entry[NUM_ENTRIES];
static GtkWidget *vbox, *label, *delete;
static addr_info *aip;
static gint edit_row;
static gchar *item_key;



/******** External function declarations ********/

GtkWidget *addressbook_get_toplevel_widget();
GtkWidget *addressbook_get_layout_widget();
void addressbook_show_main_window(gint flg);
void remove_from_list(gint row);
addr_info *get_current_record();
void update_address_list(gint row, addr_info *aip);
gint read_record_details(gchar *ks, addr_info *aip);
gint save_record_details(addr_info *aip);
gint delete_record_details(addr_info *aip);



/******** Internal function declarations ********/

static void make_edit_info(GtkWidget *vbox);
static void make_edit_area(GtkWidget *vbox);
static void make_edit_action(GtkWidget *vbox);
static void save_selected(GtkWidget *widget, GdkEvent *event, gpointer data);
static void cancel_selected(GtkWidget *widget, GdkEvent *event, gpointer data);
static void delete_selected(GtkWidget *widget, GdkEvent *event, gpointer data);
#if (ALLOW_SWITCH_RECORD == 1)
static void switch_record(GtkWidget *widget, gint mode);
#endif
static void free_record_details(addr_info *aip);
static void set_entry_values();
static void reset_entry_values();
static gint get_entry_values();
static gint assign_value(gchar *src, gchar **dst);



/******** External function definitions ********/

void show_edit_window(gint flg)
{
   if(flg)
   {
      gtk_widget_map(vbox);
   }
   else
   {
      gtk_widget_unmap(vbox);
   }

   /* either it is open or close, reset status flag */
   aip->status = RECORD_DONE;
}



void open_edit_window(gint row, gchar *key)
{
   edit_row = row;
   item_key = key;

   if(vbox == NULL)
   {
      /* Create a vertical box for layout control */
      vbox = gtk_vbox_new(FALSE, ALL_SPACE);
      gtk_widget_show(vbox);
      gtk_fixed_put(GTK_FIXED(addressbook_get_layout_widget()), vbox, 0, 0);

      make_edit_info(vbox);

      make_edit_area(vbox);
   }
   else
      show_edit_window(1);

   /* get current record and display its details */
   if(edit_row >= 0)
   {
      if(read_record_details(item_key, aip))
         set_entry_values();

      /* show delete button */
      gtk_widget_show(delete);
   }
   else
   {
      /* hide delete button */
      gtk_widget_hide(delete);

      reset_entry_values();
   }

   addressbook_show_main_window(0);
}



/******** Internal function definitions ********/

static void make_record_display(GtkWidget *tbox)
{
   gchar *s;

   aip = get_current_record();

   if(label == NULL)
   {
      /* Create a text label for showing the current date */
      label = gtk_label_new("");
      gtk_box_pack_start(GTK_BOX(tbox), label, FALSE, FALSE, 5);
      gtk_widget_show(label);
   }

   /* Update the text label for the top window */
   if(edit_row >= 0)
      s = "Address Edit";
   else
      s = "Address Add";

   gtk_label_set_text(GTK_LABEL(label), s);
}



static void make_edit_info(GtkWidget *vbox)
{
#if (ALLOW_SWITCH_RECORD == 1)
   GtkWidget *prev, *next, *dummy;
#endif
   GtkWidget *tbox;

   /* Create a topbox for showing date information */
   tbox = gtk_hbox_new(FALSE, ALL_SPACE);
   gtk_widget_set_usize(GTK_WIDGET(tbox), TOPBOX_WD, TOPBOX_HT);
   gtk_box_pack_start(GTK_BOX(vbox), tbox, FALSE, FALSE, FIRST_SPACE);
   gtk_widget_show(tbox);

   /* Create a text label for showing the current record no. */
   make_record_display(tbox);

#if (ALLOW_SWITCH_RECORD == 1)
   /* Create two buttons for changing record */
   prev = gtk_button_new_with_label("-");
   next = gtk_button_new_with_label("+");
   dummy = gtk_invisible_new();

   gtk_widget_set_usize(prev, 15, 8);
   gtk_widget_set_usize(next, 15, 8);
   gtk_widget_set_usize(dummy, 10, 8);

   gtk_box_pack_end(GTK_BOX(tbox), dummy, FALSE, FALSE, 5);
   gtk_box_pack_end(GTK_BOX(tbox), next, FALSE, FALSE, 5);
   gtk_box_pack_end(GTK_BOX(tbox), prev, FALSE, FALSE, 0);

   gtk_widget_show(prev);
   gtk_widget_show(dummy);
   gtk_widget_show(next);

   gtk_signal_connect(GTK_OBJECT(prev), "clicked",
                      GTK_SIGNAL_FUNC(switch_record),
                      (gpointer)LAST_RECORD);

   gtk_signal_connect(GTK_OBJECT(next), "clicked",
                      GTK_SIGNAL_FUNC(switch_record),
                      (gpointer)NEXT_RECORD);
#endif

	make_edit_action(tbox);
}



static void make_edit_area(GtkWidget *vbox)
{
   GtkWidget *fixed, *label;
   gint i, x, y, h;

   fixed = gtk_fixed_new();
   gtk_container_border_width(GTK_CONTAINER(fixed), 0);
   gtk_widget_set_usize(fixed, TOPLEVEL_WD, SWLIST_HT);
   gtk_box_pack_start(GTK_BOX(vbox), fixed, FALSE, FALSE, SECOND_SPACE);
   gtk_widget_show(fixed);

   i = 0;
   x = 10;
   y = 5;
   h = LIST_ROW_HT;

   for(i = 0; i < NUM_ENTRIES; i++)
   {
      label = gtk_label_new(entry_recs[i].label);

      gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
      gtk_widget_set_usize(label, 65, h);
      gtk_fixed_put(GTK_FIXED(fixed), label, x, y);
      gtk_widget_show(label);

      item_entry[i] = gtk_entry_new_with_max_length(entry_recs[i].size);

      gtk_entry_set_editable(GTK_ENTRY(item_entry[i]), TRUE);
      gtk_widget_set_usize(item_entry[i], 150, h);
      gtk_fixed_put(GTK_FIXED(fixed), item_entry[i], x + 70, y);
      gtk_widget_show(item_entry[i]);

      y += h + 2;
   }
}



static void make_edit_action(GtkWidget *cbox)
{
   GtkWidget *button;

   button = gtk_button_new_with_label("Cancel");
   gtk_box_pack_end(GTK_BOX(cbox), button, FALSE, FALSE, 0);
   gtk_signal_connect(GTK_OBJECT(button), "clicked",
                      GTK_SIGNAL_FUNC(cancel_selected), NULL);
   gtk_widget_show(button);
   
   delete = gtk_button_new_with_label("Delete");
   gtk_box_pack_end(GTK_BOX(cbox), delete, FALSE, FALSE, 0);
   gtk_signal_connect(GTK_OBJECT(delete), "clicked",
                      GTK_SIGNAL_FUNC(delete_selected), NULL);
   gtk_widget_show(delete);
   
   button = gtk_button_new_with_label("Save");
   gtk_box_pack_end(GTK_BOX(cbox), button, FALSE, FALSE, 0);
   gtk_signal_connect(GTK_OBJECT(button), "clicked",
                      GTK_SIGNAL_FUNC(save_selected), NULL);
   gtk_widget_show(button);
}



static void save_selected(GtkWidget *widget, GdkEvent *event, gpointer data)
{
   cancel_selected(NULL, NULL, NULL);
   
   /* try saving again if last save was unsuccessful */
   if(aip->status != RECORD_DONE || get_entry_values() != 0)
   {
      /* either first name or last name must not empty */
      if(strcmp(aip->fname, "") || strcmp(aip->lname, ""))
      {
         /* update old or add new record */
         if(edit_row < 0)
            aip->status = RECORD_INSERT;
         else
            aip->status = RECORD_UPDATE;

         if(! save_record_details(aip))
         {
            /* alert the user about error */
            MessageBox("Duplicate name");
            return;
         }

         aip->status = RECORD_DONE;

         update_address_list(edit_row, aip);
      }
      else
      {
         /* alert the user about error */
         MessageBox("No first or last name entered");
         return;
      }
   }

}



static void cancel_selected(GtkWidget *widget, GdkEvent *event, gpointer data)
{
   free_record_details(aip);

   addressbook_show_main_window(1);

   show_edit_window(0);
}



static void delete_selected(GtkWidget *widget, GdkEvent *event, gpointer data)
{
   if(aip->lname && aip->fname && (*aip->lname || *aip->fname))
   {
      if(delete_record_details(aip))
      {
	     cancel_selected(NULL, NULL, NULL);

         remove_from_list(edit_row);
      }
      else
         MessageBox("Record not deleted\n");
   }
   else
      MessageBox("Cannot do delete now");
}



#if (ALLOW_SWITCH_RECORD == 1)
static void switch_record(GtkWidget *widget, gint mode)
{
   gint offset;

   switch(mode)
   {
      case LAST_RECORD: offset = -1; break;
      case THIS_RECORD: offset =  0; break;
      case NEXT_RECORD: offset = +1; break;
      default: return;
   }

   make_record_display(NULL);
}
#endif


static void free_record_details(addr_info *aip)
{
   /* free memory used, no check on pointers here */
   g_free(aip->fname);
   g_free(aip->lname);
   g_free(aip->title);
   g_free(aip->cname);
   g_free(aip->work);
   g_free(aip->home);
   g_free(aip->fax);
   g_free(aip->other);
   g_free(aip->email);
   g_free(aip->address1);
   g_free(aip->address2);

   /* clear all fields in structure */
   memset((caddr_t)aip, 0, sizeof(addr_info));
}



static void set_entry_values()
{
   gtk_entry_set_text(GTK_ENTRY(item_entry[0]), aip->fname);
   gtk_entry_set_text(GTK_ENTRY(item_entry[1]), aip->lname);
   gtk_entry_set_text(GTK_ENTRY(item_entry[2]), aip->title);
   gtk_entry_set_text(GTK_ENTRY(item_entry[3]), aip->cname);
   gtk_entry_set_text(GTK_ENTRY(item_entry[4]), aip->work);
   gtk_entry_set_text(GTK_ENTRY(item_entry[5]), aip->home);
   gtk_entry_set_text(GTK_ENTRY(item_entry[6]), aip->fax);
   gtk_entry_set_text(GTK_ENTRY(item_entry[7]), aip->other);
   gtk_entry_set_text(GTK_ENTRY(item_entry[8]), aip->email);
   gtk_entry_set_text(GTK_ENTRY(item_entry[9]), aip->address1);
   gtk_entry_set_text(GTK_ENTRY(item_entry[10]), aip->address2);
}



static void reset_entry_values()
{
   gtk_entry_set_text(GTK_ENTRY(item_entry[0]), "");
   gtk_entry_set_text(GTK_ENTRY(item_entry[1]), "");
   gtk_entry_set_text(GTK_ENTRY(item_entry[2]), "");
   gtk_entry_set_text(GTK_ENTRY(item_entry[3]), "");
   gtk_entry_set_text(GTK_ENTRY(item_entry[4]), "");
   gtk_entry_set_text(GTK_ENTRY(item_entry[5]), "");
   gtk_entry_set_text(GTK_ENTRY(item_entry[6]), "");
   gtk_entry_set_text(GTK_ENTRY(item_entry[7]), "");
   gtk_entry_set_text(GTK_ENTRY(item_entry[8]), "");
   gtk_entry_set_text(GTK_ENTRY(item_entry[9]), "");
   gtk_entry_set_text(GTK_ENTRY(item_entry[10]), "");
}



static gint get_entry_values()
{
   GtkWidget **w;
   gint f;

   /* get text from entry boxes and check for modifications made */
   w = item_entry;
   f = 0;

   f |= assign_value(gtk_entry_get_text(GTK_ENTRY(w[0])), &aip->fname);
   f |= assign_value(gtk_entry_get_text(GTK_ENTRY(w[1])), &aip->lname);
   f |= assign_value(gtk_entry_get_text(GTK_ENTRY(w[2])), &aip->title);
   f |= assign_value(gtk_entry_get_text(GTK_ENTRY(w[3])), &aip->cname);
   f |= assign_value(gtk_entry_get_text(GTK_ENTRY(w[4])), &aip->work);
   f |= assign_value(gtk_entry_get_text(GTK_ENTRY(w[5])), &aip->home);
   f |= assign_value(gtk_entry_get_text(GTK_ENTRY(w[6])), &aip->fax);
   f |= assign_value(gtk_entry_get_text(GTK_ENTRY(w[7])), &aip->other);
   f |= assign_value(gtk_entry_get_text(GTK_ENTRY(w[8])), &aip->email);
   f |= assign_value(gtk_entry_get_text(GTK_ENTRY(w[9])), &aip->address1);
   f |= assign_value(gtk_entry_get_text(GTK_ENTRY(w[10])), &aip->address2);

   return f;
}



static gint assign_value(gchar *src, gchar **dst)
{
   gint f;

   /* check if value modified */
   if(*dst == NULL)
      f = (strcmp(src, "") != 0);
   else
      f = strcmp(src, *dst);

   /* update value only when modified */
   if(f != 0)
   {
      g_free(*dst);

      *dst = g_strdup(src);
   }

   /* make sure output is not NULL */
   if(*dst == NULL)
   {
      *dst = g_strdup("");

      f = 1;
   }

   /* return non-zero if value is update */
   return (f != 0);
}



