//-----------------------------------------------------------------------------
/*
 * Description: This file contains the class AxMenuMailView
 *
 * 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/05/31 12:52:20 $
 *   $Revision: 1.11 $
 */
//-----------------------------------------------------------------------------

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

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

//----- qt --------------------------------------------------------------------
//----- CORBA -----------------------------------------------------------------
//----- ICE -------------------------------------------------------------------
//----- C++ -------------------------------------------------------------------
#include <string>

//----- C ---------------------------------------------------------------------
//----- vdr -------------------------------------------------------------------
#include <vdr/tools.h>
#include <vdr/font.h>
#include <vdr/i18n.h>
#include <vdr/menuitems.h>
#include <vdr/remote.h>

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

//----- local plugin ----------------------------------------------------------
#include "AxPluginMailBox.h"
#include "AxPluginSetup.h"
#include "AxMenuMailView.h"
#include "AxMenuMailListView.h"
#include "AxVdrTools.h"
#include "AxMailTools.h"
#if ALEX_NOPORT
#include "AxOsdMailItem.h"
#endif

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

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

//-----------------------------------------------------------------------------
//     AxMenuMailView::AxMenuMailView()
//-----------------------------------------------------------------------------
AxMenuMailView::AxMenuMailView( AxPluginMailBox    *thePlugin
                              , Ax::Mail::MailBox  *theMailBox
                              , Ax::Mail::Mail     *theMail
                              , AxMenuMailListView *theMailListView
                              )
            : PARENT(       "Mail", 9)
            , myPlugin      (thePlugin )
            , myMailBox     (theMailBox)
            , myMail        (theMail   )
            , myPrevNew     (0)
            , myNextNew     (0)
            , myPrev        (0)
            , myNext        (0)
            , myMailListView(theMailListView)
            , myButtonPage  (PAGE_JUMP)
#if ALEX_NOPORT
            , mySubjectItem (0)
            , mySenderItem  (0)
            , myDateItem    (0)
            , myBodyItem    (0)
#endif
{
  wsdebug(("> AxMenuMailView::AxMenuMailView()"));

  //----- create menuitems ------------------------------------------------
#if ALEX_NOPORT
  mySubjectItem = new AxOsdItem();
  mySenderItem  = new AxOsdItem();
  myDateItem    = new AxOsdItem();

  mySubjectItem->SetFont(AxVdrTools::getDvbFont(myPlugin->getSetup()->PluginSettings.MV_HeadFont));
  mySenderItem ->SetFont(AxVdrTools::getDvbFont(myPlugin->getSetup()->PluginSettings.MV_HeadFont));
  myDateItem   ->SetFont(AxVdrTools::getDvbFont(myPlugin->getSetup()->PluginSettings.MV_HeadFont));

  mySubjectItem->SetSelectable(false);
  mySenderItem ->SetSelectable(false);
  myDateItem   ->SetSelectable(false);

  int aLine   = 6;
  int aXPos   = 1;
  int aYPos   = aLine;
  int aWidth  = Setup.OSDWidth - 1 - aXPos;
  int aHeight = Setup.OSDHeight - aLine + 2;

  tColor  aBgCol = clrBackground;
  tColor  aFgCol = clrWhite;

  myBodyItem    = new AxOsdMailItem( aXPos , aYPos
                                   , aWidth, aHeight
                                   , aFgCol, aBgCol
                                   , AxVdrTools::getDvbFont(myPlugin->getSetup()->PluginSettings.MV_BodyFont)
                                   , myPlugin->getSetup()->PluginSettings.MV_JumpSize
                                   );

  myBodyItem->setViewMode(AxOsdMailItem::MailViewMode(myPlugin->getSetup()->PluginSettings.MV_ViewMode));


  Add(mySubjectItem);
  Add(mySenderItem );
  Add(myDateItem   );
  Add(myBodyItem   );
#endif
  showMail();

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

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

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

//-------------------------------------------------------------------------
//     AxMenuMailView::Display()
//-------------------------------------------------------------------------
void AxMenuMailView::Display(void)
{
  PARENT::Display();
  DisplayMenu()->SetText(myBodyText.c_str(), true);//XXX define control character in text to choose the font???
} // AxMenuMailView::Display()

#define DEBUG_PROCESS_KEY 0

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

  //--------------------------------------------------------------------------------------------
  // scroll the text-area ('borrowed from vdr/menu.c:  eOSState cMenuText::ProcessKey(eKeys Key)
  switch (theKey)
  {
    case kUp|k_Repeat:
    case kUp:
    case kDown|k_Repeat:
    case kDown:
    case kLeft|k_Repeat:
    case kLeft:
    case kRight|k_Repeat:
    case kRight:
    {
      DisplayMenu()->Scroll( NORMALKEY(theKey) == kUp   || NORMALKEY(theKey) == kLeft   // up?
                           , NORMALKEY(theKey) == kLeft || NORMALKEY(theKey) == kRight  // page?
                           );
      wsdebug(("< AxMenuMailView::ProcessKey()      Key: %-10s  Cur: %3d  HasSub: %d  exiting early..."
            , cKey::ToString(theKey)
            , Current()
            , HasSubMenu()
            ));
      return osContinue;
      break;
    }
    default:
    {
      break;
    }
  } // switch
  //--------------------------------------------------------------------------------------------

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

#if BUILD_DEVEL
  //----- scroll through all mails -----
  static int aAutoMode = 0;
  if (theKey == kNone && aAutoMode != 0)
  {
    wsdebug(("  AxMenuMailView::ProcessKey()      putting key..."));
    if      (aAutoMode < 0)
      if (myPrev != 0) cRemote::Put(kFastRew);
      else             aAutoMode = 0;
    else if (aAutoMode > 0)
      if (myNext != 0) cRemote::Put(kFastFwd);
      else             aAutoMode = 0;
    wsdebug(("  AxMenuMailView::ProcessKey()      putting key...done"));
  } // if
#endif

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

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

  //----- select action... ----------------------------------------------------
  aState = osContinue;
  switch (theKey)
  {
#if BUILD_DEVEL
    case k1:
    {
      aAutoMode = -1;
      break;
    }
    case k2:
    {
      aAutoMode =  0;
      break;
    }
    case k3:
    {
      aAutoMode =  1;
      break;
    }
#endif
    case kBack  :
    {
      aState = osBack;
      break;
    }

    //----- jump to previous mail -----
    case kFastRew:
    case kFastRew| k_Repeat:
    case k4:
    case k4| k_Repeat:
    {
      switch (myButtonPage)
      {
        case PAGE_JUMP:
        case PAGE_MARK:
        {
          if (myPrev)
          {
            myMail = myPrev;
            showMail();
          } // if
          break;
        }
      } // switch
      break;
    }

    //----- jump to next mail -----
    case kFastFwd:
    case kFastFwd| k_Repeat:
    case k6:
    case k6| k_Repeat:
    {
      switch (myButtonPage)
      {
        case PAGE_JUMP:
        case PAGE_MARK:
        {
          if (myNext)
          {
            myMail = myNext;
            showMail();
          } // if
          break;
        }
      } // switch
      break;
    }

    //----- toggle view mode -----
    case k0:
    {
#if ALEX_NOPORT
      if (myBodyItem->getViewMode() < AxOsdMailItem::MVM_LAST)
      {
        myBodyItem->setViewMode(AxOsdMailItem::MailViewMode(myBodyItem->getViewMode() + 1));
      }
      else
      {
        myBodyItem->setViewMode(AxOsdMailItem::MVM_FIRST);
      } // if
      showMail();
      {
        char *szMsg;
        asprintf(&szMsg, "%s: %d", tr("Word-wrap mode"), myBodyItem->getViewMode());
        showStatusMsg(szMsg);
        free(szMsg);

      }
#endif
      break;
    }

    //----- RED key ---------
    case kRed:
    {
      switch (myButtonPage)
      {
        case PAGE_JUMP:
        {
          break;
        }
        case PAGE_MARK:  // ----- toggle flag: SEEN -----
        {
          if (theKey == kRed)
          {
            if (myMail->getIsSeen()) myMail->clearFlag(Mail::MF_SEEN);
            else                     myMail->setFlag  (Mail::MF_SEEN);

            // return to PAGE_JUMP and display new flags in title
            setButtons(STAY_ON_MARK_PAGE ? myButtonPage : PAGE_JUMP);
            setTitle();
          } // if
        }
      } // switch
      break;
    }

    //----- GREEN key ---------
    case k7 :
    case kGreen:
    {
      switch (myButtonPage)
      {
        case PAGE_JUMP:  //----- jump to previous new -----
        {
          if (myPrevNew)
          {
            myMail = myPrevNew;
            showMail();
          } // if
          break;
        }
        case PAGE_MARK:  // ----- toggle flag: FLAGGED -----
        {
          if (theKey == kGreen)
          {
            if (myMail->getIsFlagged()) myMail->clearFlag(Mail::MF_FLAGGED);
            else                        myMail->setFlag  (Mail::MF_FLAGGED);

            // return to PAGE_JUMP and display new flags in title
            setButtons(STAY_ON_MARK_PAGE ? myButtonPage : PAGE_JUMP);
            setTitle();
          } // if
        }
      } // switch
      break;
    }

    //----- YELLOW key ---------
    case k9 :
    case kYellow:
    {
      switch (myButtonPage)
      {
        case PAGE_JUMP: //----- jump to next new -----
        {
          if (myNextNew)
          {
            myMail = myNextNew;
            showMail();
          } // if
          break;
        }
        case PAGE_MARK:   // ----- toggle flag: DELETED -----
        {
          if (theKey == kYellow)
          {
            if (myMail->getIsDeleted()) myMail->clearFlag(Mail::MF_DELETED);
            else                        myMail->setFlag  (Mail::MF_DELETED);

            // return to PAGE_JUMP and display new flags in title
            setButtons(STAY_ON_MARK_PAGE ? myButtonPage : PAGE_JUMP);
            setTitle();
          } // if
          break;
        }
      } // switch
      break;
    }

    //----- BLUE key ---------
    case kBlue:
    {
      // switch pages
      switch (myButtonPage)
      {
        case PAGE_JUMP: setButtons(PAGE_MARK); break;
        case PAGE_MARK: setButtons(PAGE_JUMP); break;
      } // switch
      break;
    }

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

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

//-------------------------------------------------------------------------
//     AxMenuMailView::showMail()
//-------------------------------------------------------------------------
void AxMenuMailView::showMail()
{
#if 0
  wsdebug(("> AxMenuMailView::showMail() Mail: %08X  CurrentIndex: %ld"
         , int(myMail)
         , myMail ? myMail->getMailNum() : long(0)
         ));
#endif

#if ALEX_NOPORT
  if (myMail)
  {
    //----- build the text for the menu items -------------------------------
    string  aText;

    //----- Subject: --------------------------------------------------------
    aText = myMail->getSubject();
    if (!AxMailTools::decodeEncodedWords(aText, aText))
    {
      wswarn(("AxMenuMailView::showMail() unable to decode subject line '%s'", aText.c_str()));
    } // if
    aText = string(tr("Subject")) + ":\t " + aText;
    mySubjectItem->SetText(aText.c_str());

    //----- From: ------------------------------------------------------------
    aText = myMail->getFrom();
    if (!AxMailTools::decodeEncodedWords(aText, aText))
    {
      wswarn(("AxMenuMailView::showMail() unable to decode from line '%s'", aText.c_str()));
    } // if
    aText = string(tr("From"   )) + ":\t " + aText;
    mySenderItem->SetText(aText.c_str());

    //----- Date: ------------------------------------------------------------
    aText = string(tr("Date"   )) + ":\t " + myMail->getDate();
    myDateItem->SetText(aText.c_str());

    //----- Body: ------------------------------------------------------------
    myBodyItem->setMail(myMail);
  }
  else
  {
    //----- build the text for the menu items -------------------------------
    string  aText;

    //----- Subject: --------------------------------------------------------
    mySubjectItem->SetText(aText.c_str());

    //----- From: ------------------------------------------------------------
    mySenderItem->SetText(aText.c_str());

    //----- Date: ------------------------------------------------------------
    myDateItem->SetText(aText.c_str());

    //----- Body: ------------------------------------------------------------
    myBodyItem->setMail(0);
  } // if

  SetCurrent(myBodyItem);

#else

  myBodyText = "";

  if (myMail)
  {
    std::string aText;

    //----- Subject: --------------------------------------------------------
    aText = myMail->getSubject();
    if (!AxMailTools::decodeEncodedWords(aText, aText))
    {
      wswarn(("AxMenuMailView::showMail() unable to decode subject line '%s'", aText.c_str()));
    } // if
    myBodyText += string(tr("Subject")) + ":\t " + aText + "\n";

    //----- From: ------------------------------------------------------------
    aText = myMail->getFrom();
    if (!AxMailTools::decodeEncodedWords(aText, aText))
    {
      wswarn(("AxMenuMailView::showMail() unable to decode from line '%s'", aText.c_str()));
    } // if
    myBodyText += string(tr("From"   )) + ":\t " + aText + "\n";

    //----- Date: ------------------------------------------------------------
    myBodyText += string(tr("Date"   )) + ":\t " + myMail->getDate() + "\n";

    //----- Body: ------------------------------------------------------------
    myBodyText += string("\n");
    Mail::MailPartList aPartList = myMail->getFlatPartList(false);

    if (aPartList.size() > 1)
    {
      char *szLine;
      asprintf( &szLine, "---[%s]----------------------", tr("Multipart mail"));
      myBodyText += string(szLine) + "\n";
      free(szLine);
    } // if

    //----- iterate through the parts of the mail -----
    for (Mail::MailPartList::const_iterator  anIter  = aPartList.begin();
                                            anIter != aPartList.end();
                                          ++anIter)
    {
      const Mail::MailPart *aPart = *anIter;

      if (aPartList.size() > 1)
      {
        char *szLine;

        asprintf( &szLine
                , "---[%s %s: %s/%s/%s]--------"
                , "P", aPart->getPartName().c_str()
                ,      aPart->getTypeStr().c_str()
                ,      aPart->getEncStr().c_str()
                ,      aPart->getSubType().c_str()
                );

        myBodyText += string(szLine) + "\n";
        free(szLine);
        szLine = 0;
      } // if

      switch (aPart->getType())
      {
        case TYPETEXT:
        {
          myBodyText += aPart->getBodyText() + "\n";
          break;
        }
        default:
        {
          break;
        }
      } // switch
    } // for

    myBodyText += string("---[EOM]-----") + "\n";
  } // if
#endif

  //----- update title and buttons ------------------------------------------
  setButtons(myButtonPage);
  setTitle(); // this calls Display()

  myMailListView->setCurrentMail(myMail);
//  Display();
#if 0
  wsdebug(("< AxMenuMailView::showMail() '%10s' '%10s' '%10s' '%10s'"
         , aButton1Text, aButton2Text, aButton3Text, aButton4Text
         ));
#endif
} // AxMenuMailView::showMail()

//-------------------------------------------------------------------------
//     AxMenuMailView::setTitle()
//-------------------------------------------------------------------------
void AxMenuMailView::setTitle()
{
  char *szMsg = 0;
  asprintf( &szMsg
          , "%s: %ld / %ld [%s]"
          , myMailBox->getAccountName()
          , myMail ? myMail->getMailNum() : 0
          , myMailBox->getCountMails()
          , myMail ? myMail->getFlagsStr().c_str() : ""
          );

  SetTitle(szMsg);
  free(szMsg); szMsg = 0;

  Display();
} // AxMenuMailView::setTitle()

//-------------------------------------------------------------------------
//     AxMenuMailView::setButtons()
//-------------------------------------------------------------------------
void AxMenuMailView::setButtons(AxPage theButtonPage)
{
  myButtonPage = theButtonPage;

  //----- setup the buttons ---------------------------------------------
  const char *aButton1Text = 0;
  const char *aButton2Text = 0;
  const char *aButton3Text = 0;
  const char *aButton4Text = 0;

  if (myMail)
  {
    myMailBox->getSurroundings(myMail, &myPrev, &myNext, &myPrevNew, &myNextNew);

    wsdebug(("  AxMenuMailView::showMail() Prev: %3ld  PrevNew: %3ld  Act: %3ld  NextNew: %3ld  Next: %3ld"
           , myPrev    ? myPrev   ->getMailNum() : 0
           , myPrevNew ? myPrevNew->getMailNum() : 0
           , myMail    ? myMail   ->getMailNum() : 0
           , myNextNew ? myNextNew->getMailNum() : 0
           , myNext    ? myNext   ->getMailNum() : 0
           ));

    switch (myButtonPage)
    {
      //----- page jump ------------------------------------------------
      case PAGE_JUMP: // first page
      {
        if (myPrevNew) aButton2Text = tr("<< New");
        if (myNextNew) aButton3Text = tr("New >>");

        aButton4Text = tr("Flags...");
        break;
      }

      //----- page mark ------------------------------------------------
      case PAGE_MARK:
      {
        if (myMail->getIsSeen())    aButton1Text   = tr("New");
        else                        aButton1Text   = tr("Seen");

        if (myMail->getIsFlagged()) aButton2Text   = tr("Not Flagged");
        else                        aButton2Text   = tr("Flagged");

        if (myMail->getIsDeleted()) aButton3Text   = tr("Undelete");
        else                        aButton3Text   = tr("Delete"  );

        aButton4Text   = tr("Back...");
      }

      default:
      {
        break;
      }
    } // switch
  } // if

  SetHelp(aButton1Text, aButton2Text, aButton3Text, aButton4Text);
} // AxMenuMailView::setButtons()
