//-----------------------------------------------------------------------------
/*
 * Description: This file contains the class AxMenuMailBoxView
 *
 * 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:   17.11.2003
 *
 * Last modfied:
 *   $Author: alex $
 *   $Date: 2004/05/31 12:52:20 $
 *   $Revision: 1.6 $
 */
//-----------------------------------------------------------------------------

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

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

//----- qt --------------------------------------------------------------------
//----- CORBA -----------------------------------------------------------------
//----- ICE -------------------------------------------------------------------
//----- C++ -------------------------------------------------------------------
//----- C ---------------------------------------------------------------------
//----- vdr -------------------------------------------------------------------
#include <vdr/tools.h>
#include <vdr/i18n.h>
#include <vdr/menuitems.h>

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

//----- local plugin ----------------------------------------------------------
#include "AxVdrTools.h"
#include "AxMenuMailBoxView.h"
#include "AxMenuMailListView.h"
#include "AxPluginSetup.h"
#include "AxPluginMailBox.h"
#include "AxMenuCode.h"

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

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

//=============================================================================
//     class AxMailBoxItem
//=============================================================================
class AxMailBoxItem : public cOsdItem
{
  typedef cOsdItem PARENT;

  public:
    //-------------------------------------------------------------------------
    //     AxMailBoxItem()
    //-------------------------------------------------------------------------
    AxMailBoxItem(Mail::MailBox *theMailBox, eOSState State = osUnknown);

    //-------------------------------------------------------------------------
    //     ~AxMailBoxItem()
    //-------------------------------------------------------------------------
    virtual ~AxMailBoxItem();

    //-------------------------------------------------------------------------
    //     Set()
    //-------------------------------------------------------------------------
    virtual void Set(void);

    //-------------------------------------------------------------------------
    //     getMailBox()
    //-------------------------------------------------------------------------
    Mail::MailBox *getMailBox();

  private:
    //-------------------------------------------------------------------------
    //     attributes
    //-------------------------------------------------------------------------
    Mail::MailBox *myMailBox;

}; // class AxMailBoxItem

//-----------------------------------------------------------------------------
//     AxMailBoxItem::AxMailBoxItem()
//-----------------------------------------------------------------------------
AxMailBoxItem::AxMailBoxItem(Mail::MailBox *theMailBox, eOSState State)
             : PARENT(State)
             , myMailBox(theMailBox)
{
} // AxMailBoxItem::AxMailBoxItem()

//-----------------------------------------------------------------------------
//     AxMailBoxItem::~AxMailBoxItem()
//-----------------------------------------------------------------------------
AxMailBoxItem::~AxMailBoxItem()
{
} // AxMailBoxItem::~AxMailBoxItem()

//-----------------------------------------------------------------------------
//     AxMailBoxItem::getMailBox()
//-----------------------------------------------------------------------------
Mail::MailBox *AxMailBoxItem::getMailBox()
{
  return myMailBox;
} // AxMailBoxItem::getMailBox()

//-----------------------------------------------------------------------------
//     AxMailBoxItem::Set()
//-----------------------------------------------------------------------------
void AxMailBoxItem::Set(void)
{
  char *aLine = 0;

  if (getMailBox()->hasStatus())
  {
    asprintf( &aLine
            , "%ld\t%ld\t%s"
            , getMailBox()->getCountUnseen()
            , getMailBox()->getCountMails()
            , getMailBox()->getAccountName()
            );
  }
  else
  {
    asprintf( &aLine
            , "%s\t\t%s"
            , tr("???")
            , getMailBox()->getAccountName()
            );
  } // if
  wsdebug(("- AxMailBoxItem::Set() '%s'", aLine));
  SetText(aLine, false);
} // AxMailBoxItem::Set()

//=============================================================================
//     class AxMenuMailBoxView
//=============================================================================

//-----------------------------------------------------------------------------
//     AxMenuMailBoxView::AxMenuMailBoxView()
//-----------------------------------------------------------------------------
AxMenuMailBoxView::AxMenuMailBoxView(AxPluginMailBox *thePlugin)
                   : PARENT(tr     ("Mail accounts"), 6, 7)
                   , myPlugin      (thePlugin)
                   , myButtonPage  (1)
                   , myLockCodeIsOk(false)
                   , myLockMailBox (0)
{
  wsdebug(("> AxMenuMailBoxView::AxMenuMailBoxView()"));

  //----- create title line -----
  if (myPlugin->getSetup()->Accounts.size() > 0)
  {
    Mail::MailBoxMgr::instance()->setDebugCClientCallbacks(myPlugin->getSetup()->PluginSettings.DebugCClient);

    //----- create header line -----
    char *szMsg = 0;
    asprintf( &szMsg
            , "%s---------\t%s---------\t%s------------------------------------------------------------------------"
            , tr("new")
            , tr("total")
            , tr("mail account")
            );
    cOsdItem *anItem = new cOsdItem(szMsg);
    free(szMsg); szMsg = 0;
    anItem->SetSelectable(false);
    Add(anItem);

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

      //---- create menu-item and add to osd-menu -----
      AxMailBoxItem *anItem = new AxMailBoxItem(aMB);
      anItem->Set();
      Add(anItem);
    } // for

    wsdebug(("  AxMenuMailBoxView::AxMenuMailBoxView() Items created, calling Display..."));

    checkMailBoxes();
    SetCurrent(Get(1));
    setButtons(myButtonPage);
  }
  else
  {
    Skins.Message(mtStatus, tr("No mail accounts defined!"));
  } // if

  wsdebug(("< AxMenuMailBoxView::AxMenuMailBoxView()"));
} // AxMenuMailBoxView::AxMenuMailBoxView()

//-----------------------------------------------------------------------------
//     AxMenuMailBoxView::~AxMenuMailBoxView()
//-----------------------------------------------------------------------------
AxMenuMailBoxView::~AxMenuMailBoxView()
{
  wsdebug(("> AxMenuMailBoxView::~AxMenuMailBoxView()"));

  myPlugin->MainMenuActionFinished();

  wsdebug(("< AxMenuMailBoxView::~AxMenuMailBoxView()"));
} // AxMenuMailBoxView::~AxMenuMailBoxView()

#define DEBUG_PROCESS_KEY 0

//-------------------------------------------------------------------------
//     AxMenuMailBoxView::ProcessKey()
//-------------------------------------------------------------------------
eOSState AxMenuMailBoxView::ProcessKey(eKeys theKey)
{
#if DEBUG_PROCESS_KEY
  if (theKey != kNone)
  {
    wsdebug(("> AxMenuMailBoxView::ProcessKey() Key: %-10s  Cur: %3d  HasSub: %d  parent processing..."
           , cKey::ToString(theKey)
           , Current()
           , HasSubMenu()
           ));
  } // if
#endif

  bool fHasSubMenu = HasSubMenu();
  eOSState aState = PARENT::ProcessKey(theKey);

#if DEBUG_PROCESS_KEY
  if (theKey != kNone)
  {
    wsdebug(("  AxMenuMailBoxView::ProcessKey() Key: %-10s  Cur: %3d  HasSub: %d  State: %-10s  "
           , cKey::ToString(theKey)
           , Current()
           , HasSubMenu()
           , AxVdrTools::getOSStateStr(aState)
           ));
  } // if
#endif

  if (fHasSubMenu && !HasSubMenu())
  {
    wsdebug(("  AxMenuMailBoxView::ProcessKey() submenu disappeared, LockMailBox: %p  CodeOk: %d"
           , myLockMailBox, myLockCodeIsOk
           ));
    // submenu has disappeared
    if (myLockMailBox)
    {
      // -> lock screen was visible -> now display mail list view
      if (myLockCodeIsOk)
      {
        cOsdMenu *anOsdMenu = new AxMenuMailListView(myPlugin, myLockMailBox, true);
        myLockMailBox = 0;
        return AddSubMenu(anOsdMenu);
      } // if
      myLockMailBox = 0;
    }
    else if (Current() > 0)
    {
      // -> mail list view disappeared -> update current mailbox
      checkMailBox(Current());
      Skins.Message(mtStatus, NULL);
    } // if
  } // if

#if 1
  if (aState != osUnknown && fHasSubMenu)
  {
#if DEBUG_PROCESS_KEY
    if (theKey != kNone)
    {
      wsdebug(("< AxMenuMailBoxView::ProcessKey() Key: %-10s  Cur: %3d  HasSub: %d  State: %-10s  already handled"
            , cKey::ToString(theKey)
            , Current()
            , HasSubMenu()
            , AxVdrTools::getOSStateStr(aState)
            ));
    } // if
#endif
    return aState;
  } // if
#endif

  //----- select action... ----------------------------------------------------
  aState = osContinue;
  switch (theKey)
  {
    case kBack:
    {
      aState = osBack;
      break;
    }

    case kUp    :
    case kUp    | k_Repeat:
    case kDown  :
    case kDown  | k_Repeat:
    case kLeft  :
    case kLeft  | k_Repeat:
    case kRight :
    case kRight | k_Repeat:
    {
      setButtons(myButtonPage);
      break;
    }

    case kRed   :
    {
      break;
    }

    case kGreen :
    case kOk    :
    {
      if (Current() > 0)
      {
        AxMailBoxItem *aMailBoxItem = dynamic_cast<AxMailBoxItem *>(Get(Current()));

        if (aMailBoxItem)
        {
          Mail::MailBox *aMB = aMailBoxItem->getMailBox();

          if (!aMB->hasStatus())
          {
            Skins.Message(mtStatus, aMB->getLastLogMsg().c_str());
          }
          else if (aMB->getCountMails() == 0)
          {
            Skins.Message(mtStatus, tr("Mailbox is empty"));
          }
          else if (aMB->getCountMails() > 0)
          {
            cOsdMenu *anOsdMenu = 0;

            if ( aMB->getSetup()->AccessMode == Ax::Mail::MailBoxSetup::AM_SETUP_READ
              && strlen(aMB->getSetup()->AccessCode) > 0
               )
            {
              myLockCodeIsOk = false;
              myLockMailBox  = aMB;
              anOsdMenu = new AxMenuCode( aMB->getSetup()->AccessCode
                                        , sizeof(aMB->getSetup()->AccessCode) - 1
                                        , myLockCodeIsOk
                                        );
            }
            else
            {
              anOsdMenu = new AxMenuMailListView(myPlugin, aMB, true);
            } // if

            aState = AddSubMenu(anOsdMenu);
          } // if
        } // if
      } // if
      break;
    }

    case kBlue:
    {
      checkMailBoxes();
      setButtons(myButtonPage);
      break;
    }

    default     :
    {
//      aState = osUnknown;
      break;
    }
  } // switch

#if DEBUG_PROCESS_KEY
  if (theKey != kNone)
  {
    wsdebug(("< AxMenuMailBoxView::ProcessKey() Key: %-10s  Cur: %3d  HasSub: %d  State: %-10s  "
          , cKey::ToString(theKey)
          , Current()
          , HasSubMenu()
          , AxVdrTools::getOSStateStr(aState)
          ));
  } // if
#endif
  return aState;
} // AxMenuMailBoxView::ProcessKey()

//-------------------------------------------------------------------------
//     AxMenuMailBoxView::setButtons()
//-------------------------------------------------------------------------
void AxMenuMailBoxView::setButtons(int theButtonPageNum)
{
  wsdebug(("> AxMenuMailBoxView::setButtons() Current: %d", Current()));
  myButtonPage = theButtonPageNum;

  const char    *aButton1Text = 0;
  const char    *aButton2Text = 0;
  const char    *aButton3Text = 0;
  const char    *aButton4Text = tr("Refresh all");
  const char    *aStatus      = 0;
  Mail::MailBox *aMB          = 0;

  if (Current() > 0)
  {
    AxMailBoxItem *aMailBoxItem = dynamic_cast<AxMailBoxItem *>(Get(Current()));

    if (aMailBoxItem)
    {
      aMB = aMailBoxItem->getMailBox();

      switch (myButtonPage)
      {
        case 1:
        {
#if 0
          if (aMB->getCountUnseen()> 0) aButton1Text = tr("new");
#endif
          if (aMB->getCountMails() > 0) aButton2Text = tr("All");
          break;
        }
      } // switch

      if (!aMB->hasStatus())
      {
        aStatus = aMB->getLastLogMsg().c_str();
      } // if
    } // if
  } // if
  SetHelp(aButton1Text, aButton2Text, aButton3Text, aButton4Text);
  if (aStatus && aMB)
  {
    wsinfo(("%s: %s", aMB->getAccountName(), aStatus));
    Skins.Message(mtStatus, aStatus);
  }
  else
  {
    Skins.Message(mtStatus, NULL);
  } // if
//  Display();
  wsdebug(("< AxMenuMailBoxView::setButtons() Current: %d", Current()));
} // AxMenuMailBoxView::setButtons()

//-------------------------------------------------------------------------
//     AxMenuMailBoxView::checkMailBoxes()
//-------------------------------------------------------------------------
void AxMenuMailBoxView::checkMailBoxes()
{
  wsdebug(("> AxMenuMailBoxView::checkMailBoxes() Count: %d", Count()));

  // counting starts with 1 as the first (0) is the header-line
  for (int i = 1; i < Count(); ++i)
  {
    checkMailBox(i);
  } // if

  wsdebug(("< AxMenuMailBoxView::checkMailBoxes() Count: %d", Count()));
} // AxMenuMailBoxView::checkMailBoxes()

//-------------------------------------------------------------------------
//     AxMenuMailBoxView::checkMailBox()
//-------------------------------------------------------------------------
void AxMenuMailBoxView::checkMailBox(int theIndex)
{
  if (theIndex > 0 && theIndex <= Count())
  {
    AxMailBoxItem *aMailBoxItem = dynamic_cast<AxMailBoxItem *>(Get(theIndex));

    if (aMailBoxItem)
    {
      Mail::MailBox *aMB = aMailBoxItem->getMailBox();
      wsdebug(("> AxMenuMailBoxView::checkMailBoxes() checking '%s'...", aMB->getAccountName()));

      //----- show "checking mailbox <mailboxname>..." -----
      char *szMsg = 0;
      asprintf( &szMsg
              , "%s %s..."
              , tr("Checking mailbox")
              , aMB->getAccountName()
              );

      //----- only update the status-bar -----
      Skins.Message(mtStatus, szMsg);
      free(szMsg); szMsg = 0;
      Display();

      //----- update mailbox -----
      aMB->requestStatus();
      aMailBoxItem->Set();

      //----- refresh complete display because the numbers changed -----
      Display();

      wsdebug(("< AxMenuMailBoxView::checkMailBoxes() checking '%s'...DONE", aMB->getAccountName()));
    } // if
  } // if
} // AxMenuMailBoxView::checkMailBox()
