//-----------------------------------------------------------------------------
/*
 * Description: This file contains the class AxMailChecker
 *
 * See the file README in the main directory for a description of
 * this software, copyright information, and how to reach the author.
 *
 * Author: alex
 * Date:   15.11.2003
 *
 * Last modfied:
 *   $Author: alex $
 *   $Date: 2004/01/18 15:09:52 $
 *   $Revision: 1.3 $
 */
//-----------------------------------------------------------------------------

//=============================================================================
//     includes
//=============================================================================

//----- multiple defs of swap() workaround ------------------------------------
#include "AxPluginGlobals.h"

//----- qt --------------------------------------------------------------------
//----- CORBA -----------------------------------------------------------------
//----- ICE -------------------------------------------------------------------
//----- C++ -------------------------------------------------------------------
//----- C ---------------------------------------------------------------------
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

//----- vdr -------------------------------------------------------------------
#include <vdr/plugin.h>

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

//----- local -----------------------------------------------------------------
#include "AxMailChecker.h"
#include "AxPluginSetup.h"

//----- locals ----------------------------------------------------------------

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

//=============================================================================
//     consts
//=============================================================================

//=============================================================================
//     class AxMailChecker
//=============================================================================

//-------------------------------------------------------------------------
//     AxMailChecker::AxMailChecker()
//-------------------------------------------------------------------------
AxMailChecker::AxMailChecker(const AxPluginSettings *thePluginSettings)
             : myPluginSettings(thePluginSettings)
             , fExit           (true)
{
  wsdebug(("> AxMailChecker::AxMailChecker()"));
  wsdebug(("< AxMailChecker::AxMailChecker()"));
} // AxMailChecker::AxMailChecker()

//-------------------------------------------------------------------------
//     AxMailChecker::~AxMailChecker()
//-------------------------------------------------------------------------
AxMailChecker::~AxMailChecker()
{
  wsdebug(("> AxMailChecker::~AxMailChecker()"));
  wsdebug(("< AxMailChecker::~AxMailChecker()"));
} // AxMailChecker::~AxMailChecker()

//-------------------------------------------------------------------------
//     AxMailChecker::startChecking()
//-------------------------------------------------------------------------
bool AxMailChecker::startChecking()
{
  bool fOK = false;

  if (Active())
  {
    wswarn(("AxMailChecker::startChecking() thread is already executing!"));
  }
  else if (myPluginSettings->BGCheckDelay <= 0)
  {
    wsinfo(("AxMailChecker::startChecking() BGCheckDelay == 0 -> thread not started!"));
  }
  else if (Mail::MailBoxMgr::instance()->getMailBoxCltn().size() == 0)
  {
    wsinfo(("AxMailChecker::startChecking() no mail-accounts defined -> thread not started!"));
  }
#if !VDR_HAS_ASYNC_MSG
  else if (myPluginSettings->MailCmd[0] == '\0')
  {
    wsinfo(("AxMailChecker::startChecking() no mail-cmd defined (set with the '-m' option) -> thread not started!"));
  }
#endif
  else
  {
    wsdebug(("> AxMailChecker::startChecking() Active: %d", int(Active())));
    fOK = Start();
    if (!fOK)
    {
      wserror(("unable to start mail-checker-thread!"));
    } // if
    wsdebug(("< AxMailChecker::startChecking() Active: %d", int(Active())));
  } // if
  return fOK;
} // AxMailChecker::startChecking()

//-------------------------------------------------------------------------
//     AxMailChecker::stopChecking()
//-------------------------------------------------------------------------
void AxMailChecker::stopChecking()
{
  if (Active())
  {
    wsdebug(("> AxMailChecker::stopChecking() Active: %d", int(Active())));

    { // request the lock
      // (if currently a mailbox is checked, this will block until finished)
      cMutexLock aLock(&myCheckMutex);

      fExit = true;
    } // release the lock

    int aDelay = 3;
    wsdebug(("  AxMailChecker::stopChecking() calling Cancel(%d)...", aDelay));
    Cancel(aDelay);
    wsdebug(("  AxMailChecker::stopChecking() calling Cancel()...done"));

    wsdebug(("< AxMailChecker::stopChecking() Active: %d", int(Active())));
  }
  else
  {
    wsdebug(("  AxMailChecker::stopChecking() mail-checker-thread is not active!"));
  } // if
} // AxMailChecker::stopChecking()

//-------------------------------------------------------------------------
//     AxMailChecker::Action()
//-------------------------------------------------------------------------
void AxMailChecker::Action()
{
  wsinfo(("mail-checker-thread: started (pid = %d)", getpid()));

         fExit       = false;
  bool   fFirst      = true;          // is this the first check
  time_t myNextCheck = time(0) + 10;  // next check in x secs

  wsdebug(("mail-checker-thread: myCheckDelay: %d  Time: %d  NextCheck: %d"
        , myCheckDelay, int(time(0)), int(myNextCheck)));

  while (!fExit)
  {
    if (myNextCheck > time(0))
    {
      usleep(100000);
      continue;
    } // if

    //----- create mailbox list items -----
    for (Mail::MailBoxList::const_iterator anIter  = Mail::MailBoxMgr::instance()->getMailBoxCltn().begin();
                                 !fExit && anIter != Mail::MailBoxMgr::instance()->getMailBoxCltn().end();
                                         ++anIter)
    {
      Mail::MailBox *aMB = *anIter;

      if (aMB->getSetup()->BGCheckMode != Ax::Mail::MailBoxSetup::BG_MODE_NONE)
      {
        checkMailBox(*anIter, fFirst);

        // wait for a short time without lock
        if (!fExit) usleep(10000);
      } // if
    } // for

    fFirst      = false;
    myNextCheck = time(0) + (myPluginSettings->BGCheckDelay * 60);
  } // while

  wsinfo(("mail-checker-thread: stopped (pid = %d)", getpid()));
} // AxMailChecker::Action()

//-------------------------------------------------------------------------
//     AxMailChecker::checkMailBox()
//-------------------------------------------------------------------------
void AxMailChecker::checkMailBox(Mail::MailBox *theMB, bool fForceStartCmd)
{
  wsinfo(("mail-checker-thread: checking for new mail in %s...", theMB->getAccountName()));
  cMutexLock aLock(&myCheckMutex);

  long aCountUnseen = theMB->getCountUnseen();
  long aCountMails  = theMB->getCountMails ();

  wsdebug(("mail-checker-thread: before  New: %3ld  Total: %3ld, checking..."
        , aCountUnseen
        , aCountMails
        ));

  theMB->requestStatus();

  wsdebug(("mail-checker-thread: after   New: %3ld  Total: %3ld, checking...done"
        , theMB->getCountUnseen()
        , theMB->getCountMails ()
        ));

#if VDR_HAS_ASYNC_MSG
  //----- send svdrp-MESG-command ---------
  if ( aCountUnseen < theMB->getCountUnseen() && 0 < theMB->getCountUnseen()
    && ((theMB->getSetup()->BGCheckMode & Ax::Mail::MailBoxSetup::BG_MSG_MASK) == Ax::Mail::MailBoxSetup::BG_MSG_ON)
     )
  {
    char *szMsg;
    asprintf(&szMsg, "%s %s", tr("New mail in "), theMB->getAccountName());
    Interface->SetAsyncMessage(szMsg);
    free(szMsg);
  } // if
#endif

  //----- start external command -----
  if ( myPluginSettings->MailCmd[0] != '\0' && (aCountUnseen != theMB->getCountUnseen() || fForceStartCmd)
    && ((theMB->getSetup()->BGCheckMode & Ax::Mail::MailBoxSetup::BG_EXT_MASK) == Ax::Mail::MailBoxSetup::BG_EXT_ON)
     )
  {
    char *aCmd;
    asprintf( &aCmd
            , "%s \"%s\" \"%s\" dummy dummy %ld %ld %ld %ld"
            , myPluginSettings->MailCmd
            , theMB->getAccountName()
            , theMB->getLoginName()
            , theMB->getCountUnseen()
            , theMB->getCountMails()
            , aCountUnseen
            , aCountMails
            );

    wsdebug(("mail-checker-thread: executing '%s'", aCmd));
    int aRet = SystemExec(aCmd);
    if (aRet != 0)
    {
      wserror(("mail-checker-thread: unable to start '%s' (ret: %d)", aCmd, aRet));
    }
    else
    {
      wsinfo(("mail-checker-thread: Cmd: '%s' Ret: %d", aCmd, aRet));
    } // if
    free(aCmd);
  } // if

  wsdebug(("mail-checker-thread: checking for new mail in %s...done", theMB->getAccountName()));
} // AxMailChecker::checkMailBox()
