/* LinPopUp - A Linux enhanced port of Winpopup, running over Samba.
 * Copyright (c)1998-2000 Jean-Marc Jacquet <jm@littleigloo.org>  
 * Little Igloo Org  http://www.LittleIgloo.org
 *
 * 
 * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

#include "protos.h"


static GtkWidget *msg_file_sel;
static GtkWidget *send_header;
static GtkWidget *send_combo;
static GList *combo_items;




static void save_send_history (void);
static void update_send_history (char *this_name);





static int
samba_post (gchar * header_text, char *temp_filename)
{
  FILE *output;
  gchar command_line[2048];
  gchar prefix[128];
  gchar *head_copy = g_strdup (header_text);
  gchar *head_text = head_copy;
  gchar buf_line[80];
  gchar *header_master, *header_end, *quote;
  int i;
  int hlen = strlen (header_text);
  char MULTI_RECIPIENTS = (strchr (header_text, ',') != NULL);


  if (hlen > 100)		/* -- substantially less than "prefix" size -- */
    {
      alert_ok ("Error", "Send-to list is too long.", "Ok");
      g_free (head_copy);
      return FALSE;
    }



  (char *) header_end = (char *) (head_text + hlen);


  /* -- destroy erroneous embedded single-quotes. -- */
  while ((quote = strchr (head_text, '\'')) != NULL)
    *quote = '-';


  if (MULTI_RECIPIENTS)
    sprintf (prefix, "echo '[ To: %s ]\n' ; ", head_copy);


  while (head_text < header_end)
    {
      if ((header_master = strchr (head_text, ',')) != NULL)
	*header_master = '\0';
      else
	header_master = header_end;

      /* -- launch smbclient and read output from pipe -- */
      //sprintf (command_line, "( %s cat %s ) | smbclient -M \"%s\" -U \"%s\" -n \"%s\" \"%s\"", (MULTI_RECIPIENTS ? prefix : ""), temp_filename, head_text, user_rc.samba_username, user_rc.samba_nbiosname, user_rc.samba_misc);

      sprintf (command_line, "( %s cat %s ) | smbclient -M \"%s\" -U \"%s\" -n \"%s\" \"%s\" 2>&1", (MULTI_RECIPIENTS ? prefix : ""), temp_filename, head_text, user_rc.samba_username, user_rc.samba_nbiosname, user_rc.samba_misc);


      output = popen (command_line, "r");
      i = fread (command_line, 1, sizeof (command_line), output);
      pclose (output);
      command_line[i] = 0;

      /* -- sommaire investigation of the output -- */
      if (strstr (command_line, "sh: smbclient: "))
	{
	  /*
	   * don't check for "command not found", as that message can be
	   * different if another LANGuage is used than C / english
	   */
	  sprintf (buf_line, "\n`smbclient' command cannot be run;\nnot installed?");
	  alert_ok ("Error", buf_line, "Ok");
	  g_free (head_copy);
	  return FALSE;
	}

      if (strstr (command_line, "nknown host"))
	{
	  sprintf (buf_line, "\n\nUnknown host : %s", head_text);
	  alert_ok ("Error", buf_line, "Ok");
	  g_free (head_copy);
	  return FALSE;
	}

      if (strstr (command_line, "error connecting to") || (strstr (command_line, "onnection to") && strstr (command_line, "failed")))
	{
	  sprintf (buf_line, "\n\nHost unreachable :\n %s", head_text);
	  alert_ok ("Error", buf_line, "Ok");
	  g_free (head_copy);
	  return FALSE;
	}

      if (strstr (command_line, "ERRmsgoff"))
	{
	  sprintf (buf_line, "\n\n%s can't receive\nwinpopup messages.", head_text);
	  alert_ok ("Error", buf_line, "Ok");
	  g_free (head_copy);
	  return FALSE;
	}

      if (strstr (command_line, "Control-D\nsent") && strstr (command_line, "bytes"))
	{
	  if (!MULTI_RECIPIENTS && user_rc.confirm)
	    alert_ok ("LinPopUp", "\n\nMessage succesfully sent.", "Ok");
	}
      else if (!MULTI_RECIPIENTS)
	alert_ok_text ("LinPopup -smbclient output", command_line);

      head_text = header_master + 1;
    }

  g_free (head_copy);
  return TRUE;
}



void
send_send (GtkWidget * widget, gpointer * data)
{
  gchar *header_text;
  gchar message_text[2048];
  guint message_length;
  char IS_TRUNCATED = FALSE;
  char *temp_filename;
  int file_handle_temp;
  gchar new_header[256];

  /* -- retrieving header text, and checking for a  destination -- */
  if (!strlen (header_text = gtk_entry_get_text (GTK_ENTRY (send_header))))
    {
      alert_ok (" Error", "\nPlease enter a destination.", "Ok");
      return;
    }

  /* -- retrieving message text, cut big texts in parts -- */
  message_length = gtk_text_get_length (GTK_TEXT (send_text));
  if (message_length > 1400)
    {
      IS_TRUNCATED = TRUE;
      strcpy (message_text, gtk_editable_get_chars (GTK_EDITABLE (send_text), 0, 1400));
      message_length = 1400;
      while (message_text[message_length] != 10)
	--message_length;
      message_text[message_length] = 0;
      strcat (message_text, "\n=== TO BE CONTINUED ===");

      gtk_text_freeze (GTK_TEXT (send_text));
      gtk_text_set_point (GTK_TEXT (send_text), message_length);
      gtk_text_backward_delete (GTK_TEXT (send_text), message_length);
      gtk_text_set_point (GTK_TEXT (send_text), 0);

      gtk_text_thaw (GTK_TEXT (send_text));
    }
  else
    {
      gchar *pc;
      pc = gtk_editable_get_chars (GTK_EDITABLE (send_text), 0, -1);
      strcpy (message_text, pc);
      g_free (pc);
    }


  /* -- write message text to a tempory file -- */
  temp_filename = tmpnam (NULL);
  file_handle_temp = open (temp_filename, O_RDWR | O_CREAT | O_TRUNC, DATA_PERM);
  write (file_handle_temp, message_text, strlen (message_text));
  close (file_handle_temp);




  /* -- add self? -- */
  if (user_rc.self_send)
    sprintf (new_header, "%s,%s", user_rc.samba_nbiosname, header_text);
  else
    sprintf (new_header, "%s", header_text);


  /* -- cowardly posting it via samba, 
   * update and save send history,
   * and close the send window in many case-- */
  if (samba_post (new_header, temp_filename) && !IS_TRUNCATED)
    {
      update_send_history (header_text);
      save_send_history ();
      gtk_widget_destroy (send_window);
      send_window = NULL;
    }

  /* -- then remove the tempory file -- */
  unlink (temp_filename);
}



static void
send_cancel (GtkWidget * widget, gpointer * data)
{
  /* -- if a message was entered, asking for confirmation -- */
  if (gtk_text_get_length (GTK_TEXT (send_text)))
    if (alert_dialog ("", "\nA new message was entered.\n\nCancel anyway ?", "Yes", "No", 2) == 2)
      return;
  gtk_widget_destroy (send_window);
  send_window = NULL;
}



static void
message_load_ok (GtkWidget * widget, GtkFileSelection * file_sel)
{
  char *filename;

  filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_sel));
  if (filename != NULL)
    {
      FILE *in;
      char buf[1024];

      in = fopen (filename, "r");
      if (in == NULL)
	{
	  sprintf (buf, "\n    Unable to Open '%s'    \n", filename);
	  alert_ok ("File Error", buf, "ok");
	}
      else
	{
	  gtk_text_freeze (GTK_TEXT (send_text));
	  while (fgets (buf, 1024, in))
	    gtk_text_insert (GTK_TEXT (send_text), NULL, &send_text->style->black, NULL, buf, strlen (buf));
	  gtk_text_thaw (GTK_TEXT (send_text));
	  fclose (in);
	}
    }
  gtk_widget_destroy (GTK_WIDGET (file_sel));
  msg_file_sel = NULL;
}



static void
message_load_cancel (GtkWidget * widget, GtkFileSelection * file_sel)
{
  gtk_widget_destroy (GTK_WIDGET (file_sel));
  msg_file_sel = NULL;
}



void
message_load (GtkWidget * widget, gpointer data)
{
  if (msg_file_sel == NULL)
    {
      msg_file_sel = gtk_file_selection_new ("Load Message text...");
      gtk_signal_connect (GTK_OBJECT (msg_file_sel), "destroy", GTK_SIGNAL_FUNC (gtk_widget_destroy), msg_file_sel);
      gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (msg_file_sel)->ok_button), "clicked", GTK_SIGNAL_FUNC (message_load_ok), msg_file_sel);
      gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (msg_file_sel)->cancel_button), "clicked", GTK_SIGNAL_FUNC (message_load_cancel), msg_file_sel);
    }

  if (GTK_WIDGET_VISIBLE (msg_file_sel))
    return;
  else
    gtk_widget_show (msg_file_sel);
}



void
reply_message (void)
{
  if (current_showed_message)
    {
      is_it_a_reply = TRUE;
      send_message ();
    }
}






static void
update_send_history (char *this_name)
{
  char *ptr;
  GList *list = combo_items;

  while (list)
    {
      ptr = list->data;
      if (!strcmp (ptr, this_name))
	{
	  gtk_entry_set_text (GTK_ENTRY (send_header), this_name);
	  return;
	}
      list = list->next;
    }

  if (combo_items == NULL)
    combo_items = g_list_append (combo_items, strdup (this_name));
  else
    combo_items = g_list_insert (combo_items, strdup (this_name), 0);
  gtk_combo_set_popdown_strings (GTK_COMBO (send_combo), combo_items);
}




static void
load_send_history (void)
{
  FILE *history_file;
  char this_path[1024];
  char this_line[256];
  char *ptr;

  if (!(ptr = getenv ("HOME")))
    fatal_error (2, "HOME");
  sprintf (this_path, "%s/.linpopup.history", ptr);

  if (access (this_path, F_OK))
    return;
  if ((history_file = fopen (this_path, "r")) == NULL)
    return;

  while (fgets (this_line, sizeof (this_line), history_file) != NULL)
    {
      if (this_line[strlen (this_line) - 1] == '\n')
	this_line[strlen (this_line) - 1] = 0;

      if (strlen (this_line))
	combo_items = g_list_append (combo_items, strdup (this_line));
    }
  fclose (history_file);

  gtk_combo_set_popdown_strings (GTK_COMBO (send_combo), combo_items);
}





static void
save_send_history (void)
{
  FILE *history_file;
  char this_path[1024];
  GList *list = combo_items;
  char *ptr;
  int compt = MAX_SEND_HISTORY_LINES;

  if (!(ptr = getenv ("HOME")))
    fatal_error (2, "HOME");
  sprintf (this_path, "%s/.linpopup.history", ptr);

  if ((history_file = fopen (this_path, "w")) == NULL)
    return;

  while (list && compt--)
    {
      ptr = list->data;
      fprintf (history_file, "%s\n", ptr);
      list = list->next;
    }

  fflush (history_file);
  fclose (history_file);
}







void
send_message (void)
{
  GtkWidget *send_vbox;
  GtkWidget *send_statusbar;
  GtkWidget *send_frame;
  GtkWidget *send_table;
  GtkWidget *send_button_send;
  GtkWidget *send_button_cancel;
  int send_context_id;
  gint x, y, w, h;

  msg_file_sel = NULL;

  if (send_window != NULL)
    {
      gtk_widget_show (send_window);
      return;
    }

  /* -- First, the window -- */
  send_window = create_dialog_window (GTK_WINDOW_TOPLEVEL, 0, "LinPopUp", &send_vbox);
  gdk_window_get_origin (window->window, &x, &y);
  gtk_widget_set_uposition (send_window, x, y);

  gdk_window_get_size (window->window, &w, &h);
  gtk_window_set_default_size (GTK_WINDOW (send_window), w, h);

  gdk_window_set_decorations (send_window->window, GDK_DECOR_BORDER | GDK_DECOR_TITLE | GDK_DECOR_RESIZEH);

  send_text = gtk_text_new (NULL, NULL);


  /* -- Top frame first packed to the vbox -- */
  send_frame = create_frame (send_vbox, " Send to :", FALSE, TRUE, GTK_SHADOW_ETCHED_IN);
  gtk_container_border_width (GTK_CONTAINER (send_frame), 2);


  /* -- Creating frame's widgets -- */
  send_combo = gtk_combo_new ();
  gtk_combo_set_use_arrows_always (GTK_COMBO (send_combo), TRUE);
  gtk_widget_show (send_combo);
  combo_items = NULL;
  send_header = GTK_COMBO (send_combo)->entry;
  gtk_entry_set_editable (GTK_ENTRY (send_header), 1);
  load_send_history ();


  send_button_send = gtk_button_new_with_label ("Send");
  gtk_signal_connect (GTK_OBJECT (send_button_send), "clicked", GTK_SIGNAL_FUNC (send_send), NULL);
  gtk_widget_show (send_button_send);

  send_button_cancel = gtk_button_new_with_label ("Cancel");
  gtk_signal_connect (GTK_OBJECT (send_button_cancel), "clicked", GTK_SIGNAL_FUNC (send_cancel), NULL);
  gtk_widget_show (send_button_cancel);

/*-- attaching frame's widget to a table, and packing it to the frame --*/
  send_table = gtk_table_new (2, 4, TRUE);
  gtk_table_set_col_spacings (GTK_TABLE (send_table), 5);
  gtk_table_set_row_spacings (GTK_TABLE (send_table), 5);
  gtk_container_border_width (GTK_CONTAINER (send_table), 10);
  gtk_table_attach (GTK_TABLE (send_table), send_combo, 0, 3, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
  gtk_table_attach (GTK_TABLE (send_table), send_button_send, 3, 4, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
  gtk_table_attach (GTK_TABLE (send_table), send_button_cancel, 3, 4, 1, 2, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
  gtk_container_add (GTK_CONTAINER (send_frame), send_table);
  gtk_widget_show (send_table);
  gtk_widget_show (send_frame);

  /* -- create a menu below the top frame via create_send_menu defined in menu.c-- */
  create_send_menu (send_vbox);

  /* -- and a text area via create_text defined in text.c -- */
  create_text_area (send_text, send_vbox);
  gtk_text_set_editable (GTK_TEXT (send_text), 1);

  /* -- and finally a statusbar -- */
  send_statusbar = gtk_statusbar_new ();
  gtk_box_pack_start (GTK_BOX (send_vbox), send_statusbar, FALSE, TRUE, 0);
  gtk_widget_show (send_statusbar);
  send_context_id = gtk_statusbar_get_context_id (GTK_STATUSBAR (send_statusbar), " ");

  /* -- show the window -- */
  gtk_widget_show (send_window);

  /* -- connecting the send_cancel function to the delete event -- */
  gtk_signal_connect (GTK_OBJECT (send_window), "delete_event", GTK_SIGNAL_FUNC (send_cancel), NULL);


  /* -- fill the deliver adress if required -- */
  switch (user_rc.deliver)
    {
    case DHOST:
      gtk_entry_set_text (GTK_ENTRY (send_header), user_rc.deliver_adr);
      break;
    case GUESS:
      if (!strcmp (user_rc.guess_adr, "?"))
	gtk_entry_set_text (GTK_ENTRY (send_header), user_rc.deliver_adr);
      else
	gtk_entry_set_text (GTK_ENTRY (send_header), user_rc.guess_adr);
      break;
    case BLANK:
    default:
      break;
    }


  /* -- If this is a reply, fill the destination and text field -- */
  if (is_it_a_reply)
    {
      struct linpopup_message this_message;
      char buf[2045];
      int char_pos_text, char_pos_buf;
      GdkColormap *colormap;

      colormap = gtk_widget_get_colormap (send_window);
      gdk_color_alloc (colormap, &user_rc.quoted_text_col);

      read_message (current_showed_message, &this_message);
      gtk_entry_set_text (GTK_ENTRY (send_header), this_message.host);	//We answer to a host not to a user

      sprintf (buf, "%c %s \n%c ---\n", user_rc.quote, user_rc.quote_string, user_rc.quote);
      strexpand (buf, "HOST", this_message.host);
      strexpand (buf, "USER", this_message.sender);

      gtk_text_freeze (GTK_TEXT (send_text));
      gtk_text_insert (GTK_TEXT (send_text), NULL, &user_rc.quoted_text_col, NULL, buf, -1);

      char_pos_buf = 0;
      buf[char_pos_buf++] = user_rc.quote;
      buf[char_pos_buf++] = 32;

      for (char_pos_text = 0; char_pos_text < strlen (this_message.text); char_pos_text++)
	{
	  buf[char_pos_buf++] = this_message.text[char_pos_text];
	  if (this_message.text[char_pos_text] == 10)
	    {
	      buf[char_pos_buf++] = user_rc.quote;
	      buf[char_pos_buf++] = 32;
	    }
	}

      buf[char_pos_buf++] = 10;
      buf[char_pos_buf++] = user_rc.quote;
      buf[char_pos_buf] = 0;

      /* -- quoted text appears in user defined color -- */
      strcat (buf, " ---");
      gtk_text_insert (GTK_TEXT (send_text), NULL, &user_rc.quoted_text_col, NULL, buf, -1);
      gtk_text_insert (GTK_TEXT (send_text), NULL, &send_text->style->black, NULL, "\n", -1);

      gtk_text_thaw (GTK_TEXT (send_text));
      gtk_text_set_editable (GTK_TEXT (send_text), 1);
      gtk_widget_grab_focus (send_text);

      is_it_a_reply = FALSE;
    }
}

/*  EOF */
