//-----------------------------------------------------------------------------
/*
 * Description: This file contains the callback functions for c-client-library
 *
 * See the file README in the main directory for a description of
 * this software, copyright information, and how to reach the author.
 *
 * The comments of the functions are copied as a reminder and for faster
 * access from the documentation of c-client.
 *
 * Author: alex
 * Date:   15.11.2003
 *
 * Last modfied:
 *   $Author: alex $
 *   $Date: 2003/12/19 18:54:44 $
 *   $Revision: 1.6 $
 */
//-----------------------------------------------------------------------------

//=============================================================================
//     includes
//=============================================================================
//----- qt --------------------------------------------------------------------
//----- CORBA -----------------------------------------------------------------
//----- ICE -------------------------------------------------------------------
//----- C++ -------------------------------------------------------------------
#include <algorithm>

//----- C ---------------------------------------------------------------------
//----- AxLib -----------------------------------------------------------------
#include <Ax/Tools/Trace.h>
// #include <Ax/Tools/TraceOn.h>
#include <Ax/Tools/Globals.h>
#include <Ax/Mail/MailBox.h>
#include <Ax/Mail/MailBoxMgr.h>

//----- vdr -------------------------------------------------------------------
//----- local plugin ----------------------------------------------------------
//----- locals ----------------------------------------------------------------


//=============================================================================
//     static
//=============================================================================
namespace Ax
{
  namespace Mail
  {
    bool DebugCClientCallbacks = false;
  }; // namespace Mail
}; // namespace Ax

//=============================================================================
//     defines
//=============================================================================
#define wscinfo(XX...) if (DebugCClientCallbacks) wsinfo(XX)

//=============================================================================
//     using namespaces
//=============================================================================
using namespace std;
using namespace Ax::Mail;

//=============================================================================
//     c-client callbacks
//=============================================================================

//-----------------------------------------------------------------------------
//     mm_dlog()
//-----------------------------------------------------------------------------
/** Log an event to debugging telemetry
 *
 * This function is called to deliver a debugging telemetry
 * message.  No newline is included in the string, so this function has
 * to output its own.  This is called only when debugging is enabled.
 *
 * @param string  message string
 */
void mm_dlog(char *string)
{
  AX_UNUSED_ARG(string);
  wscinfo(("mm_dlog: '%s'", string));
} // mm_dlog()

//-----------------------------------------------------------------------------
//     mm_flags()
//-----------------------------------------------------------------------------
/** Message flags update seen
 *
 * This function is called when c-client manipulates the flags for
 * the given message number.  This alerts the application that it may
 * need to inspect that message's flags to see if there are any
 * interesting changes.
 *
 *  @param stream  where event happened
 *  @param number  message number
 */

void mm_flags(MAILSTREAM *stream, unsigned long number)
{
  AX_UNUSED_ARG(stream);
  AX_UNUSED_ARG(number);
  wscinfo(("mm_flags: number: %ld", number));
} // mm_flags()

//-----------------------------------------------------------------------------
//     mm_status()
//-----------------------------------------------------------------------------
/** Mailbox status
 *
 * This function is called when c-client reports status of a mailbox
 * (generally as the result of a mail_status() function call).
 *
 * @param stream   stream where event happened
 * @param mailbox  mailbox name for this status
 * @param status   MAILSTATUS structure with message status
 */
void mm_status(MAILSTREAM *stream, char *mailbox, MAILSTATUS *status)
{
  AX_UNUSED_ARG(stream );
  AX_UNUSED_ARG(mailbox);
  AX_UNUSED_ARG(status );

  wscinfo(("mm_status: mailbox: '%s'  %lu total, %lu unseen, %lu recent"
        , mailbox
        , status->messages
        , status->unseen
        , status->recent
        ));

  MailBox *aMB = MailBoxMgr::instance()->getMailBox(stream);
  if (aMB)
  {
    wscinfo(("mm_status: MailBox found!"));
    aMB->processMailStatus(status);
  }
  else
  {
    wscinfo(("mm_status: MailBox NOT found!"));
  } // if
} // mm_status()

//-----------------------------------------------------------------------------
//     mm_searched()
//-----------------------------------------------------------------------------
/** Message matches a search
 *
 * This function is called to notify the main program that this
 * message number matches a search (generally as the result of a
 * mail_search_full() function call).
 *
 * @param stream  stream where event happened
 * @param number  message number
 */
void mm_searched(MAILSTREAM *stream, unsigned long msgno)
{
  AX_UNUSED_ARG(msgno );
  AX_UNUSED_ARG(stream);
  wscinfo(("mm_searched: number: %lu", msgno));
//  fatal ("impossible mm_searched() call");
} // mm_searched()

//-----------------------------------------------------------------------------
//     mm_exists()
//-----------------------------------------------------------------------------
/** Message exists (i.e. there are that many messages in the mailbox)
 *
 * This function is called to notify the main program that there are
 * this many messages in the mailbox.  It is also used to notify the main
 * program of new mail, by announcing a higher number than the main
 * program was previously aware.
 *
 * @param stream  stream where event happened
 * @param number  message number
 */
void mm_exists(MAILSTREAM *stream, unsigned long number)
{
  AX_UNUSED_ARG(stream);
  AX_UNUSED_ARG(number);
  wscinfo(("mm_exists: number: %lu", number));
} // mm_exists()

//-----------------------------------------------------------------------------
//     mm_expunged()
//-----------------------------------------------------------------------------
/** Message expunged
 *
 * This function is called to notify the main program that this
 * message number has been expunged from the mail file and that all
 * subsequent messages are now referenced by a message number one less
 * than before.  This implicitly decrements the number of messages in the
 * mailbox.
 *
 * @param stream  stream where event happened
 * @param number  message number
 */
void mm_expunged(MAILSTREAM *stream, unsigned long number)
{
  AX_UNUSED_ARG(stream);
  AX_UNUSED_ARG(number);
  wscinfo(("mm_expunged: number: %lu", number));
} // mm_expunged()

//-----------------------------------------------------------------------------
//     mm_list()
//-----------------------------------------------------------------------------
/** Mailbox found
 *
 * This function is called to notify the main program that this
 * mailbox name matches a mailbox listing request (generally as the
 * result of a mail_list() function call).  The hierarchy delimiter is a
 * character that separates out levels of hierarchy in mailbox names.
 *
 * @param stream  stream where event happened
 * @param delim   hierarchy delimiter
 * @param name    mailbox name
 * @param attrib  mailbox attributes
 */
void mm_list(MAILSTREAM *stream, int delimiter, char *name, long attributes)
{
  AX_UNUSED_ARG(stream    );
  AX_UNUSED_ARG(delimiter );
  AX_UNUSED_ARG(name      );
  AX_UNUSED_ARG(attributes);
  wscinfo(("mm_list: delimiter: '%c'  attr: %04lX  name: '%s'", delimiter, attributes, name));
} // mm_list()

//-----------------------------------------------------------------------------
//     mm_login()
//-----------------------------------------------------------------------------
/** Get user name and password for this host
 *
 * This function is called to get a user name and password for the
 * given network mailbox.  It stores the user name and password in the
 * strings pointed to by the appropriate arguments.  The trial argument
 * is the number of attempts to perform the login and is initially zero
 * (e.g. for a default username and password login functionality).  It is
 * incremented for each subsequent trial until the maximum number of
 * trials are made.
 *
 * @param mb      parsed mailbox specification
 * @param user    pointer to where to return user name
 * @param pwd     pointer to where to return password
 * @param trial   number of prior login attempts
 */
void mm_login(NETMBX *mb, char *username, char *password, long trial)
{
  AX_UNUSED_ARG(trial);
  wscinfo(("mm_login: host: '%s'  user: '%s'  mailbox: '%s'  service: '%s'"
        , mb->host, mb->user, mb->mailbox, mb->service
        ));

  MailBox *aMB = MailBoxMgr::instance()->getActiveMailBox();
  if (aMB)
  {
    if (*mb->user)
    {
      strcpy (username, mb->user);
    }
    else
    {
      strcpy(username, aMB->getLoginName());
    } // if

    strcpy(password, aMB->getLoginPass());
  }
  else
  {
    wserror(("mm_login: no MailBox active!"));
  } // if
} // mm_login

//-----------------------------------------------------------------------------
//     mm_lsub()
//-----------------------------------------------------------------------------
/** Subscribe mailbox found
 *
 * This function is called to notify the main program that this
 * mailbox name matches a subscribed mailbox listing request (generally
 * as the result of a mail_lsub() function call).  The hierarchy
 * delimiter is a character that separates out levels of hierarchy in
 * mailbox names.
 *
 * @param stream  stream where event happened
 * @param delim   hierarchy delimiter
 * @param name    mailbox name
 * @param attrib  mailbox attributes
 */
void mm_lsub(MAILSTREAM *stream, int delimiter, char *name, long attributes)
{
  AX_UNUSED_ARG(stream    );
  AX_UNUSED_ARG(delimiter );
  AX_UNUSED_ARG(name      );
  AX_UNUSED_ARG(attributes);

  wscinfo(("mm_lsub: delimiter: '%c'  attr: %04lX  name: '%s'", delimiter, attributes, name));
} // mm_lsub()

//-----------------------------------------------------------------------------
//     mm_log()
//-----------------------------------------------------------------------------
/** Log an event for the user to see
 *
 * This function is called to deliver a log message.  No newline is
 * included in the string, so this function has to output its own.  In
 * general, it is intended that these messages are logged someplace, and
 * possibly shown to the user.
 *
 * @param string  message string
 * @param errflg  message error level
 */
void mm_log(char *string, long errflg)
{
  switch (errflg)
  {
    case BYE:	// server sayonara
    case NIL:	// no error
    {
      // if (verbosep) printf ("[%s]\n",string);
      wscinfo(("mm_log: L: '%s'", string));
      break;
    }

    case PARSE: // parsing problem
    case WARN:  // warning
    {
      // fprintf (stderr,"%%%s\n",string);
      wswarn(("mm_log: W: '%s'", string));
      break;
    }

    case ERROR: // error
    {
      // fprintf (stderr,"?%s\n",string);
      wserror(("mm_log: E: '%s'", string));
      break;
    }

    default:
    {
      // fprintf (stderr,"?%s\n",string);
      wserror(("mm_log: D: '%s'", string));
      break;
    }
  } // switch

  MailBox *aMB = MailBoxMgr::instance()->getActiveMailBox();
  if (aMB)
  {
    aMB->processLogMsg(string, errflg);
  }

} // mm_log()

//-----------------------------------------------------------------------------
//     mm_notify()
//-----------------------------------------------------------------------------
/** Notification event
 *
 * This function is called to deliver a stream-oriented message
 * event.  This is the mechanism by which any IMAP response codes for any
 * application (e.g. TRYCREATE) are delivered to the application.
 * No newline is included in the string, so this function has to output
 * its own.
 *
 * @param stream  stream where event happened
 * @param string  message string
 * @param errflg  message error level
 */
void mm_notify(MAILSTREAM *stream, char *string, long errflg)
{
  AX_UNUSED_ARG(stream);
  // just do mm_log action
  mm_log(string, errflg);
} // mm_notify()

//-----------------------------------------------------------------------------
//     mm_critical()
//-----------------------------------------------------------------------------
/** About to enter critical code
 *
 * This function is called to alert the application that c-client
 * is about to run some critical code on that stream that may result in a
 * clobbered mail file if it is interrupted.  It may be desirable to
 * disable CTRL/C, etc. during this time.
 *
 * @param stream  stream where event happened
 */
void mm_critical(MAILSTREAM *stream)
{
  AX_UNUSED_ARG(stream    );
  wserror(("mm_critical: stream: %p", stream));
  //  critical = T;  /* note in critical code */
} // mm_critical()

//-----------------------------------------------------------------------------
//     mm_nocritical()
//-----------------------------------------------------------------------------
/** About to exit critical code
 *
 * This function is called to alert the application that c-client
 * is no longer running critical code on that stream that may result in a
 * clobbered mail file if it is interrupted.
 *
 * @param stream  stream where event happened
 */
void mm_nocritical (MAILSTREAM *stream)
{
  AX_UNUSED_ARG(stream    );
  wswarn(("mm_nocritical: stream: %p", stream));
  //  critical = NIL;		/* note not in critical code */
} // mm_nocritical()

//-----------------------------------------------------------------------------
//     mm_diskerror()
//-----------------------------------------------------------------------------
/** Disk error found
 *
 * This function is called to alert the application that the
 * c-client has encountered an unrecoverable write error when trying to
 * update the mail file.  errcode contains the system error code.  If
 * serious is non-zero, then it is probable that the disk copy of the
 * mailbox has been damaged.
 *
 * The return value from this function is the abort flag; if serious
 * is zero and the abort flag is non-zero, the operation is aborted.  If
 * the abort flag is zero or if serious was non-zero, a return from this
 * function will retry the failing operation.
 *
 * @param stream   stream where event happened
 * @param errcode  OS error code for disk error
 * @param serious  non-zero if c-client can not undo the operation (and
 *                 thus must retry to avoid mail file damage)
 */
long mm_diskerror(MAILSTREAM *stream, long errcode, long serious)
{
  AX_UNUSED_ARG(stream );
  AX_UNUSED_ARG(errcode);
  AX_UNUSED_ARG(serious);
  wserror(("mm_diskerror: stream: %p  errcode: %ld  serious: %ld"
         , stream, errcode, serious
         ));
  return T;
} // mm_diskerror()

//-----------------------------------------------------------------------------
//     mm_fatal()
//-----------------------------------------------------------------------------
/** Log a fatal error event
 *
 * This function is called from the fatal() routine in the
 * operating system code to notify the main program that it is about to
 * crash.  The string contains a reason.  At the very minimum, the main
 * program should do something like
 * mm_log (string,ERROR);
 * and then return.  No newline is included in the string, so this
 * function has to output its own.
 *
 * @param string  message string
 */
void mm_fatal(char *string)
{
  wserror(("mm_fatal: '%s'", string));
} // mm_fatal()

