/*
* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). 
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: This file implements class CIpsPlgImap4Plugin.
*
*/



#include "emailtrace.h"
#include "ipsplgheaders.h"
#include <baseplugincommonutils.h>     // CleanupResetAndDestroyPushL

const TInt KConnectOpPriority = CActive::EPriorityStandard;

// ---------------------------------------------------------------------------
// CIpsPlgImap4Plugin::CIpsPlgImap4Plugin()
// ---------------------------------------------------------------------------
//
CIpsPlgImap4Plugin::CIpsPlgImap4Plugin()
    : CIpsPlgSosBasePlugin( KIpsPlgImap4PluginUidValue )
    {
    FUNC_LOG;
    // none
    }


// ---------------------------------------------------------------------------
// CIpsPlgImap4Plugin::ConstructL()
// ---------------------------------------------------------------------------
//
void CIpsPlgImap4Plugin::ConstructL()
    {
    FUNC_LOG;
    BaseConstructL();
    }


// ---------------------------------------------------------------------------
// CIpsPlgImap4Plugin::NewL()
// ---------------------------------------------------------------------------
//
EXPORT_C CIpsPlgImap4Plugin* CIpsPlgImap4Plugin::NewL()
    {
    FUNC_LOG;
    CIpsPlgImap4Plugin* self = CIpsPlgImap4Plugin::NewLC();
    CleanupStack::Pop( self );
    return self;
    }


// ---------------------------------------------------------------------------
// CIpsPlgImap4Plugin::NewLC()
// ---------------------------------------------------------------------------
//
EXPORT_C CIpsPlgImap4Plugin* CIpsPlgImap4Plugin::NewLC()
    {
    FUNC_LOG;
    CIpsPlgImap4Plugin* self = new( ELeave ) CIpsPlgImap4Plugin;
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;
    }


// ---------------------------------------------------------------------------
// CIpsPlgImap4Plugin::~CIpsPlgImap4Plugin()
// ---------------------------------------------------------------------------
//
CIpsPlgImap4Plugin::~CIpsPlgImap4Plugin()
    {
    FUNC_LOG;
    }

// ---------------------------------------------------------------------------
// CIpsPlgImap4Plugin::MailboxHasCapabilityL
// ---------------------------------------------------------------------------
//
TBool CIpsPlgImap4Plugin::MailboxHasCapabilityL(
    TFSMailBoxCapabilities aCapability,
    TFSMailMsgId /* aMailBoxId */ )
    {
    FUNC_LOG;
    TBool result( EFalse );
    
    switch ( aCapability )
        {
        // These should be clear    
        case EFSMBoxCapaCanBeDeleted:
        case EFSMBoxCapaSupportsSaveToDrafts:
        case EFSMBoxCapaMeetingRequestRespond:
        case EFSMboxCapaSupportsAttahmentsInMR:
        case EFSMBoxCapaMeetingRequestCreate:
        case EFSMBoxCapaCanUpdateMeetingRequest:
        case EFSMBoxCapaMoveToFolder:
        case EFSMBoxCapaCopyToFolder:
        case EFSMBoxCapaSupportsSync:
        case EFSMBoxCapaRemoveFromCalendar:
        case EFSMBoxCapaMoveMessageNoConnectNeeded:
            {
            result = ETrue;
            break;
            }
        // These are positively not supported 
        case EFSMBoxCapaCreateSubfolder:
        case EFSMBoxCapaManipulateUserFolders: 
        case EFSMBoxCapaMoveMessageToUserFolder:
        case EFSMBoxCapaSmartReply:
        case EFSMBoxCapaSmartForward:
        case EFSMBoxCapaSupportsMRU:
        case EFSMBoxCapaSymbianMsgIntegration:
        case EFSMBoxCapaNewEmailNotifications:
        default:
            {
            result = EFalse;
            break;
            }
        }
    
    return result;
    }

// ---------------------------------------------------------------------------
// CIpsPlgImap4Plugin::RefreshNowL( )
// ---------------------------------------------------------------------------
//  
TInt CIpsPlgImap4Plugin::RefreshNowL( )
    {
    FUNC_LOG;
    return KErrNone;	
    }

// ---------------------------------------------------------------------------
// CIpsPlgImap4Plugin::RefreshNowL()
// ---------------------------------------------------------------------------
//
void CIpsPlgImap4Plugin::RefreshNowL(
    const TFSMailMsgId& aMailBoxId,
    MFSMailRequestObserver& aOperationObserver,
    TInt aRequestId )
    {
    FUNC_LOG;
    
    TMsvId service = aMailBoxId.Id();
    
    CIpsPlgSingleOpWatcher* watcher = CIpsPlgSingleOpWatcher::NewL( *this );
    CleanupStack::PushL( watcher );
    
    CIpsPlgBaseOperation* op = CIpsPlgImap4ConnectOp::NewL(
    		*iSession,
    		KConnectOpPriority, 
    		watcher->iStatus, 
    		service,
    		ActivityTimerL( aMailBoxId ),
          	aMailBoxId, 
          	aOperationObserver,
          	aRequestId,
          	iEventHandler );
    
    watcher->SetOperation( op );
    iOperations.AppendL( watcher );
    CleanupStack::Pop( watcher );
    
    // send part of refresh
    EmptyOutboxL( aMailBoxId );
    }

// ---------------------------------------------------------------------------
// CIpsPlgImap4Plugin::ListFoldersL()
// ---------------------------------------------------------------------------
//  
void CIpsPlgImap4Plugin::ListFoldersL(
    const TFSMailMsgId& aMailBoxId,
    const TFSMailMsgId& aFolderId,
    RPointerArray<CFSMailFolder>& aFolderList)
	{
    FUNC_LOG;
	DoListFoldersL( aMailBoxId, aFolderId, aFolderList, ETrue );
	}

// ---------------------------------------------------------------------------
//  CIpsPlgImap4Plugin::ListFoldersL()
// ---------------------------------------------------------------------------
//  
void CIpsPlgImap4Plugin::ListFoldersL(
    const TFSMailMsgId& aMailBoxId,
    RPointerArray<CFSMailFolder>& aFolderList)
 	{
    FUNC_LOG;
 	DoListFoldersL( aMailBoxId, TFSMailMsgId(), aFolderList, EFalse );
 	}

// ---------------------------------------------------------------------------
// CIpsPlgImap4Plugin::GetStandardFolderIdL()
// ---------------------------------------------------------------------------
//       
TFSMailMsgId CIpsPlgImap4Plugin::GetStandardFolderIdL( 
    const TFSMailMsgId& aMailBoxId, 
    const TFSFolderType aFolderType )
 	{
    FUNC_LOG;
    TFSMailMsgId ret;
    
    if( aFolderType == EFSInbox )
        {
        CMsvEntry* cEntry = iSession->GetEntryL( aMailBoxId.Id() );
        CleanupStack::PushL( cEntry );
        
        TInt i( 0 );
        TInt count( cEntry->Count() );
        while ( i < count && ret.IsNullId() )
            {
            if ( (*cEntry)[i].iType == KUidMsvFolderEntry &&
                 (*cEntry)[i].iDetails.CompareF( KIpsPlgInbox ) == 0 )
                {
                ret.SetId( (*cEntry)[i].Id() );
                }
            i++;
            } 
        CleanupStack::PopAndDestroy( cEntry );
        }
    else if( aFolderType == EFSOutbox )
        {
        ret.SetId( KMsvGlobalOutBoxIndexEntryId );
        }
    else if( aFolderType == EFSDraftsFolder )
        {
        ret.SetId( KMsvDraftEntryId );
        }
    else if( aFolderType == EFSSentFolder )
        {
        ret.SetId( KMsvSentEntryId );
        }
    else if( aFolderType == EFSDeleted )
        {
        ret.SetId( KMsvDeletedEntryFolderEntryId );
        }
    else if( aFolderType == EFSOther )
        {
        ret.SetId( KMsvUnknownServiceIndexEntryId );
        }
    if ( !ret.IsNullId() )
        {
        ret.SetPluginId( KIpsPlgImap4PluginUid );
        }
        
    return ret;
 	}
	 
// ---------------------------------------------------------------------------
// CIpsPlgImap4Plugin::FetchMessagesL()
// ---------------------------------------------------------------------------
//   
void CIpsPlgImap4Plugin::FetchMessagesL(
    const TFSMailMsgId& aMailBoxId, 
    const TFSMailMsgId& aFolderId,
    const RArray<TFSMailMsgId>& aMessageIds,
    TFSMailDetails /*aDetails*/,
    MFSMailRequestObserver& aObserver,
    TInt aRequestId)
     {
    FUNC_LOG;
 	
    CIpsPlgSingleOpWatcher* watcher = CIpsPlgSingleOpWatcher::NewL(*this);
    CleanupStack::PushL( watcher );

    CMsvEntrySelection* sel = new(ELeave) CMsvEntrySelection;
    CleanupStack::PushL(sel);
    sel->AppendL( aMailBoxId.Id() );
    
    TInt count = aMessageIds.Count();
    
    if ( count == 0 )
        {
        User::Leave( KErrArgument );
        }
    for ( TInt i(0); i < count; i++ )
        {
        sel->AppendL( aMessageIds[i].Id() );
        }
    
    
    // fetch body texts only (text/plain, text/html)
    TImImap4GetPartialMailInfo info;
    info.iMaxEmailSize = KMaxTInt32;
    info.iGetMailBodyParts = EGetImap4EmailBodyText;
    info.iPartialMailOptions = EBodyTextOnly;
    info.iTotalSizeLimit = KMaxTInt32;
    info.iBodyTextSizeLimit = KMaxTInt32;
    info.iAttachmentSizeLimit = 0;
    info.iDestinationFolder = aFolderId.Id();
    
    CIpsPlgBaseOperation* op = CIpsPlgImap4PopulateOp::NewL( 
        *iSession, 
        watcher->iStatus,
        CActive::EPriorityStandard,
        aMailBoxId.Id(),
        ActivityTimerL( aMailBoxId ),
        info,
        *sel,
        aMailBoxId, 
        aObserver,
        aRequestId,
        iEventHandler, 
        EFalse ); // do not filter mail selection
    
    watcher->SetOperation( op );
    CleanupStack::PopAndDestroy( sel );
    iOperations.AppendL( watcher );
    CleanupStack::Pop( watcher );

 	}
 	
// ---------------------------------------------------------------------------
// CIpsPlgImap4Plugin::MoveMessagesL( )
// ---------------------------------------------------------------------------  
// 
void CIpsPlgImap4Plugin::MoveMessagesL( 
    const TFSMailMsgId& aMailBoxId, 
    const RArray<TFSMailMsgId>& aMessageIds, 
    const TFSMailMsgId& aSourceFolderId, 
    const TFSMailMsgId& aDestinationFolderId )
    {
    FUNC_LOG;
    if( aDestinationFolderId.Id() == KMsvDraftEntryId  )
        {
        // Move to Drafts folder
        MoveMessagesToDraftL( aMailBoxId, 
                aMessageIds, 
                aSourceFolderId, 
                aDestinationFolderId );
        }
    else if( aDestinationFolderId.Id() != aSourceFolderId.Id() )
        {
        TMsvId service = aMailBoxId.Id();

        CIpsPlgSingleOpWatcher* watcher = CIpsPlgSingleOpWatcher::NewL(*this);
        CleanupStack::PushL( watcher );
        
        CMsvEntrySelection* sel = new(ELeave) CMsvEntrySelection;
        CleanupStack::PushL(sel);
        sel->AppendL( service );

        TInt msgIdCount( aMessageIds.Count() );
        for ( TInt i(0); i< msgIdCount; i++ )
            {
            sel->AppendL( aMessageIds[i].Id() );
            }

        TPckgBuf<TImImap4GetMailInfo> optionsBuf;
        TImImap4GetMailInfo& options = optionsBuf();
        options.iMaxEmailSize = KMaxTInt32;
        options.iGetMailBodyParts = EGetImap4EmailHeaders;
        options.iDestinationFolder = aDestinationFolderId.Id();

        CIpsPlgImap4MoveRemoteOpObserver* observer =
            CIpsPlgImap4MoveRemoteOpObserver::NewL( *iSession, *iEventHandler,
                aSourceFolderId, aMessageIds );
        watcher->SetRequestObserver( observer );

        // Synchronous operation
        CIpsPlgBaseOperation* op = CIpsPlgImap4MoveRemoteOp::NewL(
            *iSession, 
            watcher->iStatus,
            KIMAP4MTMMoveMailSelectionWhenAlreadyConnected,
            service,
            ActivityTimerL( aMailBoxId ),
            options,
            *sel,
            aMailBoxId,
            *observer, // async not supported
            0 ); // async not supported

        watcher->SetOperation( op );
        CleanupStack::PopAndDestroy( sel );
        iOperations.AppendL( watcher );
        CleanupStack::Pop( watcher );
        }
    else
        {
        //do nothing
        }
    }

// ---------------------------------------------------------------------------
// CIpsPlgImap4Plugin::MoveMessagesL()
// asynchronic move message function
// ---------------------------------------------------------------------------
//
TInt CIpsPlgImap4Plugin::MoveMessagesL( 
    const TFSMailMsgId& aMailBoxId,
    const RArray<TFSMailMsgId>& aMessageIds, 
    const TFSMailMsgId& aSourceFolderId,
    const TFSMailMsgId& aDestinationFolderId,
    MFSMailRequestObserver& aOperationObserver,
    TInt aRequestId )
    {
    FUNC_LOG;
    TInt ret = KErrNone;
    if( aDestinationFolderId.Id() == KMsvDraftEntryId  )
        {
        // Move to Drafts folder
        MoveMessagesToDraftL( aMailBoxId, 
                aMessageIds, 
                aSourceFolderId, 
                aDestinationFolderId );
        TFSProgress progress = { 
                TFSProgress::EFSStatus_RequestComplete, 0, 0, ret };
        aOperationObserver.RequestResponseL( 
                progress, aRequestId );
        }
    else if( aDestinationFolderId.Id() != aSourceFolderId.Id() )
        {
        TMsvId service = aMailBoxId.Id();

        CIpsPlgSingleOpWatcher* watcher = CIpsPlgSingleOpWatcher::NewL(*this);
        CleanupStack::PushL( watcher );
        
        CMsvEntrySelection* sel = new(ELeave) CMsvEntrySelection;
        CleanupStack::PushL(sel);
        sel->AppendL( service );

        TInt msgIdCount( aMessageIds.Count() );
        for ( TInt i(0); i< msgIdCount; i++ )
            {
            sel->AppendL( aMessageIds[i].Id() );
            }

        TPckgBuf<TImImap4GetMailInfo> optionsBuf;
        TImImap4GetMailInfo& options = optionsBuf();
        options.iMaxEmailSize = KMaxTInt32;
        options.iGetMailBodyParts = EGetImap4EmailBodyTextAndAttachments;
        options.iDestinationFolder = aDestinationFolderId.Id();

        CIpsPlgBaseOperation* op = CIpsPlgImap4MoveRemoteOp::NewL(
            *iSession, 
            watcher->iStatus,
            KIMAP4MTMMoveMailSelectionWhenAlreadyConnected,
            service,
            ActivityTimerL( aMailBoxId ),
            options,
            *sel,
            aMailBoxId,
            aOperationObserver,
            aRequestId ); 

        watcher->SetOperation( op );
        CleanupStack::PopAndDestroy( sel );
        iOperations.AppendL( watcher );
        CleanupStack::Pop( watcher );
        }
    else
        {
        ret = KErrNotSupported;
        TFSProgress progress = { 
                TFSProgress::EFSStatus_RequestComplete, 0, 0, ret };
        aOperationObserver.RequestResponseL( 
                progress, aRequestId );
        }
    return ret;
    }

// ---------------------------------------------------------------------------
// CIpsPlgImap4Plugin::FetchMessagePartsL()
// ---------------------------------------------------------------------------
//
void CIpsPlgImap4Plugin::FetchMessagePartsL(
    const TFSMailMsgId& aMailBoxId,
    const TFSMailMsgId& aFolderId,
    const TFSMailMsgId& aMessageId,
    const RArray<TFSMailMsgId>& aMessagePartIds,
    MFSMailRequestObserver& aOperationObserver,
    const TInt aRequestId,
    const TUint /*aPreferredByteCount*/)
    {
    FUNC_LOG;
    
    TInt count( aMessagePartIds.Count() );
    if ( 0 == count )
        {
        User::Leave( KErrArgument );
        } 
    
    CIpsPlgSingleOpWatcher* watcher = CIpsPlgSingleOpWatcher::NewL( *this );
    CleanupStack::PushL( watcher );
    
    CMsvEntrySelection* sel = new(ELeave) CMsvEntrySelection;
    CleanupStack::PushL( sel );
    
	TMsvEntry tEntry;
    TMsvId service;
	
    for ( TInt i(0); i < count; i++ )
        {
        sel->AppendL( aMessagePartIds[i].Id() );
        
        iSession->GetEntry( aMessagePartIds[i].Id(), service, tEntry );
        
        if ( tEntry.iType.iUid == KUidMsvEmailHtmlEntryValue ||
             tEntry.iType.iUid == KUidMsvEmailExternalBodyEntryValue ||
             tEntry.iType.iUid == KUidMsvEmailRtfEntryValue )
            {
            CleanupStack::PopAndDestroy(2);//sel, watcher
            
            //we need to fetch the whole message in these cases, because
            //symbian components ignore these types of parts currently
            RArray<TFSMailMsgId> messages(1);
            messages.Append( aMessageId );
            
            // not used in function
            TFSMailDetails dymmy = EFSMsgDataStructure;
            
            FetchMessagesL( aMailBoxId,
                            aFolderId,
                            messages,
                            dymmy,
                            aOperationObserver,
                            aRequestId );
            
            messages.Close();
                        
            return;
            }
        
        }
    
    TPckgBuf<TImImap4GetMailInfo> optionsBuf;
    TImImap4GetMailInfo& options = optionsBuf();
    options.iMaxEmailSize = KMaxTInt32;
    options.iGetMailBodyParts = EGetImap4EmailAttachments;
    options.iDestinationFolder = 0; // not used
    
    CIpsPlgBaseOperation* op = CIpsPlgImap4FetchAttachmentOp::NewL( 
        *iSession, watcher->iStatus, KIMAP4MTMPopulate, aMailBoxId.Id(),
        ActivityTimerL( aMailBoxId ), options, *sel, aMailBoxId,
        aOperationObserver, aRequestId );
    
    watcher->SetOperation( op );
    CleanupStack::PopAndDestroy( sel );
    iOperations.AppendL( watcher );
    CleanupStack::Pop( watcher );
    }

// ----------------------------------------------------------------------------
// CIpsPlgImap4Plugin::PopulateNewMailL( )
// ----------------------------------------------------------------------------
//
void CIpsPlgImap4Plugin::PopulateNewMailL( 
    const TFSMailMsgId& aMailboxId, TMsvId aNewId, TMsvId /*aParentId*/ )
    {
    FUNC_LOG;
    if ( aMailboxId.PluginId().iUid != PluginId() )
        {
        return;
        }
    else if ( iSyncStateHandler->GetMailboxIpsState( aMailboxId.Id() )
            == KIpsSosEmailSyncStarted )
        {
        return;
        }
    
    
    TMsvEntry tEntry;
    TMsvId serv;
    iSession->GetEntry( aMailboxId.Id(), serv, tEntry );
    if ( !tEntry.Connected() )
        {
        return;
        }
    
    CImImap4Settings* settings = new ( ELeave ) CImImap4Settings();
    CleanupStack::PushL( settings );
    CEmailAccounts* accounts = CEmailAccounts::NewLC();
    TImapAccount imapAcc;
    accounts->GetImapAccountL( aMailboxId.Id(), imapAcc );
    accounts->LoadImapSettingsL( imapAcc, *settings );
    TImImap4GetPartialMailInfo info;
    CIpsSetDataApi::ConstructImapPartialFetchInfo( info, *settings );
    CleanupStack::PopAndDestroy( 2, settings );
    
    if ( info.iTotalSizeLimit == KIpsSetDataHeadersOnly )
        {
        return;
        }
    
    TPckgBuf<TImImap4GetPartialMailInfo> package(info);
    
    CIpsPlgSingleOpWatcher* watcher = CIpsPlgSingleOpWatcher::NewL(*this);
    CleanupStack::PushL( watcher );

    CMsvEntrySelection* sel = new(ELeave) CMsvEntrySelection;
    CleanupStack::PushL(sel);
    sel->AppendL( aMailboxId.Id() );
    sel->AppendL( aNewId );
    
    CIpsPlgBaseOperation* op = CIpsPlgImap4PopulateOp::NewL( 
        *iSession, 
        watcher->iStatus,
        KIMAP4MTMPopulateMailSelectionWhenAlreadyConnected,
        aMailboxId.Id(),
        ActivityTimerL( aMailboxId ),
        info,
        *sel,
        aMailboxId, 
        *this,
        KErrNotFound,
        iEventHandler,
        EFalse ); // do not block entry changed and created events
    
    watcher->SetOperation( op );
    CleanupStack::PopAndDestroy( sel );
    iOperations.AppendL( watcher );
    CleanupStack::Pop( watcher );
    
    iEventHandler->SetNewPropertyEvent( 
            aMailboxId.Id(), KIpsSosEmailSyncStarted, KErrNone );
    
    }


// ---------------------------------------------------------------------------
// CIpsPlgImap4Plugin::HandleOpCompletedL()
// ---------------------------------------------------------------------------
//
void CIpsPlgImap4Plugin::HandleOpCompletedL( 
							CIpsPlgSingleOpWatcher& /*aOpWatcher*/, 
							TInt /*aCompletionCode*/ )
    {
    FUNC_LOG;

    }

// ---------------------------------------------------------------------------
//  CIpsPlgImap4Plugin::DoListFoldersL( )
// ---------------------------------------------------------------------------
//   	
void CIpsPlgImap4Plugin::DoListFoldersL( 
							TFSMailMsgId aMailBoxId,
    						TFSMailMsgId aFolderId,
    						RPointerArray<CFSMailFolder>& aFolderList,
    						TBool aOnlyDirect )
    
    {
    FUNC_LOG;
    CFSMailFolder* folder( NULL );
	CMsvEntrySelection* folders = new (ELeave) CMsvEntrySelection;
	CleanupStack::PushL( folders );
	
	if( aFolderId.IsNullId() )
	    {
        folder = GetFolderByUidL( aMailBoxId, 
                                  GetStandardFolderIdL( 
                                          aMailBoxId, EFSOutbox ) );
        if( folder )
     	    {
     	    CleanupStack::PushL( folder );
     	    aFolderList.AppendL( folder );
     	    CleanupStack::Pop( folder );
     	    }
        
        folder = GetFolderByUidL( aMailBoxId, 
                                  GetStandardFolderIdL( 
                                          aMailBoxId, EFSDraftsFolder ) );
        if( folder )
     	    {
     	    CleanupStack::PushL( folder );
     	    aFolderList.AppendL( folder );
     	    CleanupStack::Pop( folder );
     	    } 	    
     	    
        folder = GetFolderByUidL( aMailBoxId, 
                                  GetStandardFolderIdL( 
                                          aMailBoxId, EFSSentFolder ) );
        if( folder )
     	    {
     	    CleanupStack::PushL( folder );
     	    aFolderList.AppendL( folder );
     	    CleanupStack::Pop( folder );
     	    } 	   
        
        // List root level (aOnlyDirect==ETrue) or all subfolders of 
        // given mailbox (aOnlyDirect==EFalse)
        HandleFoldersL( aMailBoxId, *folders, aOnlyDirect );
	    }
    else
        {
	    // Folder id defined, list direct subfolders of given
	    // folder
        HandleFoldersL( aFolderId, *folders, aOnlyDirect );
        }
    TInt folderCount( folders->Count() );
    for( TInt i(0); i < folderCount; i++ )
        {
        aFolderId.SetId( (*folders).At(i) );
        aFolderId.SetPluginId( KIpsPlgImap4PluginUid );
        
        folder = GetFolderByUidL( aMailBoxId, aFolderId );

        CleanupStack::PushL( folder );
        aFolderList.AppendL( folder );
        CleanupStack::Pop( folder );
        }
    CleanupStack::PopAndDestroy( folders );
    }	
    
// ---------------------------------------------------------------------------
// CIpsPlgImap4Plugin::HandleFoldersL( )
// ---------------------------------------------------------------------------	
//
void CIpsPlgImap4Plugin::HandleFoldersL( 
							TFSMailMsgId aId, 
							CMsvEntrySelection& aFolders,
							TBool aOnlyDirect )
	{
    FUNC_LOG;
	if( HasChildFoldersL( aId.Id() ) )
	    {
	    // GetChildrenL is recursive, so we set CMsvEntry once and pass it
	    // forward instead of creating it several times before the first one 
	    // is deleted.
	    CMsvEntry* cEntry = iSession->GetEntryL( aId.Id() );
	    CleanupStack::PushL( cEntry );	    
	    CMsvEntrySelection* folderEntries = 
	    	GetChildrenL( aId.Id(), *cEntry, aOnlyDirect );
	    CleanupStack::PopAndDestroy( cEntry );
	    CleanupStack::PushL( folderEntries );
		
	    TInt count = folderEntries->Count();
	    for( TInt i(0); i < count; i++ )
	        {
	        aFolders.AppendL( folderEntries->At(i) );
	        }

        CleanupStack::PopAndDestroy( folderEntries );
        }
    else
        {
        // Do nothing, only subfolders of given folder will be added to array
        }
	}

// ---------------------------------------------------------------------------
// CIpsPlgImap4Plugin::GetChildrenL( )
// ---------------------------------------------------------------------------
//
CMsvEntrySelection* CIpsPlgImap4Plugin::GetChildrenL( 
											TMsvId aId, 
											CMsvEntry& aEntry,
											TBool aOnlyDirect ) const
    {
    FUNC_LOG;
    aEntry.SetEntryL( aId );
    CMsvEntrySelection* children = 
    	aEntry.ChildrenWithTypeL( KUidMsvFolderEntry );
    CleanupStack::PushL( children );

	if( !aOnlyDirect )
		{
		TInt count = children->Count();
	    for( TInt i = 0; i < count; i++ )
	        {
	        if( HasChildFoldersL( children->At(i) ) )
	            {
	            // Recursive
	            CMsvEntrySelection* grandChildren = 
	            	GetChildrenL( children->At(i), aEntry, aOnlyDirect );
	            CleanupStack::PushL( grandChildren );

		    TInt count = grandChildren->Count();
	            for( TInt k(0); k < count; k++ )
	                {
	                children->AppendL( grandChildren->At(k) );
	                }
	            CleanupStack::PopAndDestroy( grandChildren );
	            }
	        }
		}
    CleanupStack::Pop( children );
    return children;
    }
    	    
// ---------------------------------------------------------------------------
// CIpsPlgImap4Plugin::HasChildFoldersL( )
// ---------------------------------------------------------------------------
//
TBool CIpsPlgImap4Plugin::HasChildFoldersL( TMsvId aId ) const
	{
    FUNC_LOG;
	CMsvEntry* cEntry = iSession->GetEntryL( aId );
    CleanupStack::PushL( cEntry );
	TInt index = cEntry->Count()-1;
	while ( index >= 0 && (*cEntry)[index].iType != KUidMsvFolderEntry )
        {
		index--;
        }
    CleanupStack::PopAndDestroy( cEntry );

	return ( index != -1 );
	}
	        
// End of File

