static const char* version_id =
  "$Id: handle_message.cc,v 1.13 1999/10/05 15:13:03 v2kea318 Exp $";

// $Log: handle_message.cc,v $
// Revision 1.13  1999/10/05  15:13:03  v2kea318
// Rewrote the autoreply system using the new AutoReply class.
//
// Revision 1.12  1999/09/30  20:37:27  v2kea318
// If we are requested to, and the message type is ROUTE, send an automatic
// reply to the sender of the message.
//
// Revision 1.11  1999/08/17  14:32:53  v2kea318
// *** empty log message ***
//
// Revision 1.10  1999/08/16  17:00:46  v2kea318
// Use a MutexRep object rather than a Mutex to represent the mutex.  The
// properties is this representation are cleaner and safer.
//
// Revision 1.9  1999/08/09  15:11:28  v2kea318
// Remove the use of the Mutex::initialize() method.  This is now private
// in the Mutex class.
//
// Revision 1.8  1999/08/06  18:58:46  v2kea318
// Read the message from the socket in this routine rather than having
// the message passed to us.
//
// Revision 1.7  1999/08/05  19:51:48  v2kea318
// When we fail to open the log file, make sure we release the mutex
// before returning.
//
// Revision 1.6  1999/08/05  19:34:48  v2kea318
// Log messages after they are updated to the window.
//
// Revision 1.5  1999/07/06  17:02:07  v2kea318
// Allocate the ConversationWindow object in a separate routine, to be called
// in a single threaded environment, i.e. before the daemon starts accepting
// messages from the server.  This ensures a single construction of the window
// object.
//
// Revision 1.4  1999/07/02  14:54:50  v2kea318
// Do not reset the pointer to the window object to NULL when closing the
// window.  There is no need for this to be done.
//
// Revision 1.3  1999/07/01  21:44:37  v2kea318
// Changed the callback routine to not do any direct window manipulation.
// That properly belongs in the ConversationWindow object, where it now is.
//
// Revision 1.2  1999/07/01  17:02:44  v2kea318
// Redesigned the code to dump all messages to a single window.  When I learn
// how to make multiple windows, this will probably change.  Everything works,
// except the callback function destroy_conversation_window, which correctly
// destroys the window but subsequent attempts to recreate the window don't
// work.  The error is likely not here, but in ConversationWindow.
//
// Revision 1.1  1999/06/30  15:23:04  v2kea318
// Initial revision
//
//***************************************************************************

#include "handle_message.h"
#include "ConversationWindow.h"
#include "msg_constants.h"
#include "MutexRep.h"
#include "env_var.h"
#include <pwd.h>
#include <userpw.h>
#include <unistd.h>
#include <iostream>
#include <fstream>
#include <ctime>
#include "string-transfer.h"
#include "action_transfer.h"
#include "route-message.h"

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

static ConversationWindow* window = NULL;
static string* logfile_fname = NULL;
static MutexRep log_mutex;

static void log_message(const string& msg_text, const string& user,
			const msg_action_code tp, const string& timestmp);
static void receive_message(const Socket& server, string& user_id, 
			    string& text);

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

// Provide a call back function that will destroy the window.
void destroy_conversation_window(Widget w, XtPointer client_data,
				 XtPointer call_data)
{
  ConversationWindow::destroy_force_rebuild();
}

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

void* handle_message(void* p)
{
  // get the parameters.
  HandleMessageParms* parms = static_cast<HandleMessageParms *>(p);
  Pointer<Socket> socket    = parms->socket;
  msg_action_code msg_type  = parms->tp;
  const AutoReply& areply   = parms->areply;

  // free the memory.
  delete parms;

  // build the time stamp.
  time_t ctime = time(NULL);
  char* ctime_s = asctime(localtime(&ctime));
  *strrchr(ctime_s, '\n') = '\0';
  string time_stamp(ctime_s);

  // recieve the message text.
  string uid, msg_text;
  receive_message(*socket, uid, msg_text);

  // update the window.
  window->update(msg_type, msg_text, uid, time_stamp);

  // log the message.
  log_message(msg_text, uid, msg_type, time_stamp);

  // see if we need to autoreply.
  if (msg_type == ROUTE && areply) {
    try {
      msg(uid, areply.message());
    } catch (...) {
      // Eat the exception.  We don't care what it was.
    }
  }

  // return value.
  return NULL;
}

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

void handle_message_initialize()
{
  window = new ConversationWindow;
  try {
    logfile_fname = new string(get_env_var(log_file_environ_var));
  } catch (const no_env_variable&) { // not defined, so use a default.
    // get the user's home directory.
    string home_dir(getpwuid(getuid())->pw_dir);

    // build the string.
    logfile_fname = new string(home_dir + string("/msg.log"));
  }
}

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

void log_message(const string& text, const string& user, 
		 const msg_action_code t, const string& timestmp)
{
  static const char* logfile_name = logfile_fname->c_str();

  // grab the mutex to block other threads.
  MutexRep lm(log_mutex);

  // open the file to append.
  ofstream logf(logfile_name, ios::out | ios::app, 0600);
  if (!logf) {
    cerr << "Unable to open log file." << endl;
    return;
  }

  // add the stuff.
  logf << "__" << ((t == COPY) ? "To" : "From") << ": "
       << user << " [" << timestmp << "]" << endl << text << endl << endl;

  // close the file.
  logf.close();
}

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

static void receive_message(const Socket& server, string& user_id, 
			    string& text)
{
  // get the user id string.
  read_string(server, user_id);

  // get the text string.
  read_string(server, text); 
  
  // tell the server all is wonderful in the world.
  send_action(server, success, false);
}
