//  Beta release only.
//
//  Copyright(c) Ivyware Pty Ltd 2013  (all rights reserved)
//               MELBOURNE, VICTORIA, AUSTRALIA, 3130
//
//  Provided no fee is charged (either by the distributer or user)
//  permission to use, copy, modify, and distribute this software and
//  its documentation for any purpose and without fee is hereby granted,
//  provided that the above copyright notice appear in all copies and
//  that both that copyright notice and this permission notice appear
//  in supporting documentation.
//
//  No waranty or suitablity for purpose is implied.
//
//
//  IMAPISession interface wrapper class implementation
//  NOTES: Manages all subordinate IMAPISession resources including single
//         message store

#include "stdafx.h"
#include "P2Pevent.h"
#include "MAPIEx.h"
#include "MAPISession.h"
#include "MAPI_Ext.h"

/////////////////////////////////////////////////////////////
// CMAPISession

CMAPISession::CMAPISession ( CMAPIEx *pMAPIex )
{
    m_pMAPIex_      = pMAPIex;
	  m_pIMAPISession = nullptr;
    m_pCMsgStore    = nullptr;
}

CMAPISession::~CMAPISession()
{
    CloseMsgStore();
    LogoffEx();
}

//
//  Logs into MAPI and creates a session
//  NOTES: Refer LogoffEx() for complimentary logoff sequence.
//       : Only single session supported per CMAPISession instance
//       : Refer MAPISLogonEx() for parameter definitions
//
//  Parameters:  ulUIParam
//
//               LPCTSTR lpszProfileName
//
//               LPCTSTR lpszPassword
//
//               FLAGS flFlags
// 
HRESULT
CMAPISession::LogonEx ( ULONG ulUIParam, LPCTSTR lpszProfileName, LPCTSTR lpszPassword, FLAGS flFlags )
{
    if ( m_pIMAPISession )
      EVERR_MAPI(0,"Already logged in")->Throw();
    if ( flFlags == 0 )
      flFlags = MAPI_EXTENDED | MAPI_USE_DEFAULT | MAPI_NEW_SESSION
	            | MAPI_EXPLICIT_PROFILE | MAPI_NT_SERVICE;

    // Implementation
    HRESULT hr = MAPILogonEx ( ulUIParam
                             , (LPTSTR)lpszProfileName
                             , (LPTSTR)lpszPassword
                             , flFlags
                             , &m_pIMAPISession );
    if ( hr != S_OK )
      EVERR_MAPI(hr,"MAPILogonEx() failed")->AFP(ulUIParam)->AFP(lpszProfileName)->AFP(flFlags)->SetLast();
	  return hr;
}

//
//  Logs out of MAPI and closes session
//  NOTES: Refer LogonEx() for complimentary logon sequence.
//       : Only single session supported per CMAPISession instance
// 
void
CMAPISession::LogoffEx ( )
{
    CloseMsgStore();
	  RELEASE(m_pIMAPISession);
}

///////////////////////////////////////////////////////////////////////////////
//  Message store activities
//  NOTES: Refer CMsgStore for IMsgStore interface management

//
//  Opens nominated message store (configured email address0
//  NOTES: Refer GetCMsgStore() for pointer access
//
//  Parameters:  LPCTSTR lpszMsgStorename
//               Message store name (example myname@whatever.com)
//
//               ULONG ulFlags
//
//  Returns:     HRESULT
//               Standard error error.  Refer GetP2Pevent() for retrieval of
//               full description
HRESULT
CMAPISession::OpenMsgStore ( LPCTSTR lpszMsgStorename, ULONG ulMDBFlags )
{
    HRESULT hr = S_OK;
    // Pre-requisits
    if ( m_pIMAPISession == nullptr )
      THROW_MAPI(0,"Not logged in");

	  //m_ulMDBFlags=ulFlags;

    // Access Message Stores table
	  P2PsafeSRowSet spRowSet;
	  const int nProperties=3;
    CComPtr<IMAPITable> pIMsgStoresTable;
	  hr = m_pIMAPISession -> GetMsgStoresTable ( 0, &pIMsgStoresTable );
    if ( hr != S_OK )
      return MAPI_HRESULT(hr,"IMAPISession::GetMsgStoresTable() failed");

	  SizedSPropTagArray ( nProperties, Columns) = {nProperties,{PR_DISPLAY_NAME, PR_ENTRYID, PR_DEFAULT_STORE}};
		hr = pIMsgStoresTable -> SetColumns ( (LPSPropTagArray)&Columns, 0 );
    if ( hr != S_OK )
      return MAPI_HRESULT(hr,"IMAPITable::SetColumns() failed");

    // Isolate nominated store table
		while ( pIMsgStoresTable->QueryRows(1,0,spRowSet) == S_OK ) 
		{
			if ( spRowSet->cRows != 1 )
        break;                         // End of list
      if ( lpszMsgStorename    == nullptr ||
           lpszMsgStorename[0] == 0          )
      {
         if ( !spRowSet->aRow[0].lpProps[2].Value.b    )
          continue;                    // Not the default
      }

      if ( lpszMsgStorename    &&
           lpszMsgStorename[0]    )
			{
         CString strMsgStorename = MAPI_GetValidString(spRowSet->aRow[0].lpProps[0]);
				 if ( strMsgStorename != lpszMsgStorename )
              continue;
      }

      // Retrieve located message store
      //RELEASE(m_pIMsgStore);
      CComPtr<IMsgStore> pIMsgStore;
		  hr = m_pIMAPISession -> OpenMsgStore ( NULL
                                           , spRowSet->aRow[0].lpProps[1].Value.bin.cb
                                           , (ENTRYID*)spRowSet->aRow[0].lpProps[1].Value.bin.lpb
                                           , NULL,MDB_NO_DIALOG | MAPI_BEST_ACCESS
                                           , &pIMsgStore );
      if ( hr != S_OK )
        return MAPI_HRESULT ( hr, "IMAPISession::OpenMsgStore() failed");
      m_pCMsgStore = new CMsgStore ( this, pIMsgStore, ulMDBFlags );
      return S_OK;
    }

    return EVERR->MODULE
                ->Message("Message store [%s] does not exist", lpszMsgStorename )
                ->SetLast()->GetHRESULT();
}

HRESULT
CMAPISession::CloseMsgStore ( )
{
    delete m_pCMsgStore;
           m_pCMsgStore = 0;
    return S_OK;
}

BOOL
CMAPISession::GetEmail(ADRENTRY& adrEntry, CString& strEmail)
{
	LPSPropValue pProp=PpropFindProp(adrEntry.rgPropVals,adrEntry.cValues, PR_ADDRTYPE);
	if(!pProp) pProp=PpropFindProp(adrEntry.rgPropVals,adrEntry.cValues, PR_ADDRTYPE_A);
	if(pProp) 
	{
		CString strAddrType;
		MAPI_GetNarrowString(*pProp, strAddrType);
		if(strAddrType==_T("EX")) 
		{
			pProp=PpropFindProp(adrEntry.rgPropVals,adrEntry.cValues, PR_ENTRYID);

			SBinary entryID;
			entryID.cb=pProp->Value.bin.cb;
			entryID.lpb=pProp->Value.bin.lpb;

			return GetExEmail(entryID, strEmail);
		}
	}
	pProp=PpropFindProp(adrEntry.rgPropVals,adrEntry.cValues, PR_EMAIL_ADDRESS);
	if(!pProp) pProp=PpropFindProp(adrEntry.rgPropVals,adrEntry.cValues, PR_EMAIL_ADDRESS_A);
	if(pProp) 
	{
		MAPI_GetNarrowString(*pProp, strEmail);
		return TRUE;
	}
	return FALSE;
}

BOOL
CMAPISession::GetExEmail(SBinary entryID, CString& strEmail)
{
	BOOL bResult=FALSE;
	if(!m_pIMAPISession) return FALSE;

	LPADRBOOK pAddressBook;
	if(m_pIMAPISession->OpenAddressBook(0, NULL, AB_NO_DIALOG, &pAddressBook)==S_OK) 
	{
		ULONG ulObjType;
		IMAPIProp* pItem=NULL;
		if(pAddressBook->OpenEntry(entryID.cb, (ENTRYID*)entryID.lpb, NULL,MAPI_BEST_ACCESS, &ulObjType, (LPUNKNOWN*)&pItem)==S_OK) 
		{
			if(ulObjType==MAPI_MAILUSER) 
			{
				LPSPropValue pProp;
				ULONG ulPropCount;
				ULONG pSMTP[]={ 1, PR_SMTP_ADDRESS };
				ULONG pEmail[]={ 1, PR_EMAIL_ADDRESS };

				if(pItem->GetProps((LPSPropTagArray)pSMTP, T_MAPI_UNICODE, &ulPropCount, &pProp)==S_OK) 
				{
					strEmail=MAPI_GetValidString(*pProp);
					MAPIFreeBuffer(pProp);
					bResult=TRUE;
				}
				if(!bResult && pItem->GetProps((LPSPropTagArray)pEmail, T_MAPI_UNICODE, &ulPropCount, &pProp)==S_OK) 
				{
					strEmail=MAPI_GetValidString(*pProp);
					MAPIFreeBuffer(pProp);
					bResult=TRUE;
				}
			}
			RELEASE(pItem);
		}
		RELEASE(pAddressBook);
	}
	return bResult;
}

///////////////////////////////////////
//  Property exposure

IMAPISession*
CMAPISession::GetIMAPISession ( )
{
    return m_pIMAPISession;
}

CMsgStore*
CMAPISession::GetMsgStore ( )
{
    return m_pCMsgStore;
}
