/*
* Copyright (c) 2008 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:  CAknIconSrvPrecacher class.
*
*
*/

#ifdef PRECACHE2
#include <e32std.h>
#include <fbs.h>
#include <barsread.h>
#include <barsc.h>
#include "AknIconSrvPrecacher.h"
#include "AknIconSrv.h"
#include <AknIconSrv.rsg>
#include "AknIconTraces.h"

#include "AknIconSrv.h"
#include "AknIconLoader.h"
#include "AknIconSrvCache.h"
#include "AknIconSrvDef.h"
#include "AknIconManager.h"
#include "AknIconSrvIconItem.h"
#include "AknIconSrvUtils.h"
#include "AknIconUtils.h"
#include "mifconvdefs.h"
#include "AknSvgFormatHandler.h"
#include "akniconconfig.h"
#include "AknIconFormatHandlerFactory.h"

_LIT( KAknIconResourceFile, "z:\\resource\\akniconsrv.rsc" );

// -----------------------------------------------------------------------------
// 2 Phase Construction
// -----------------------------------------------------------------------------
CAknIconSrvPrecacher::CAknIconSrvPrecacher( CAknIconServer& aServer ) :
    iServer(aServer)
    {
    }

// -----------------------------------------------------------------------------
// 2 Phase Construction
// -----------------------------------------------------------------------------
CAknIconSrvPrecacher* CAknIconSrvPrecacher::NewL( CAknIconServer& aServer )
    {
    CAknIconSrvPrecacher* self = new( ELeave ) CAknIconSrvPrecacher( aServer );
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop();
    return self;
    }

// -----------------------------------------------------------------------------
// 2 Phase Construction
// -----------------------------------------------------------------------------
void CAknIconSrvPrecacher::ConstructL()
    {
    User::LeaveIfError( iFs.Connect() );
    iSvgFormatHandler = CAknSvgFormatHandler::NewL();
    User::LeaveIfError( RFbsSession::Connect() );
    }

// -----------------------------------------------------------------------------
// Destructor
// -----------------------------------------------------------------------------
CAknIconSrvPrecacher::~CAknIconSrvPrecacher()
    {
    delete iLoader;
    delete iSvgFormatHandler;
    RFbsSession::Disconnect();
    iFs.Close();
    }
    
// -----------------------------------------------------------------------------
// Start reading from precache list
// -----------------------------------------------------------------------------
void CAknIconSrvPrecacher::Start()
    {
    HBufC8* res = NULL ;
    TRAPD(err, res = SetupL());
    if (err == KErrNone)
        {
        TResourceReader reader;
        reader.SetBuffer( res );

        TRAPD(merror, ReadPrecacheItemsL( reader));

        if(merror != KErrNone)
            {
#ifdef __AKNICON_TRACES
            RDebug::Printf("Error Processing Precacher List");
#endif
            }

        iServer.iPrecacheComplete = ETrue;
        RThread thread;
        thread.Suspend();
        
        while (iServer.iFreePrecacheBitmapHandles.Count())
            {
            CFbsBitmap* bitmap = iServer.iFreePrecacheBitmapHandles[0];
            delete bitmap;
            iServer.iFreePrecacheBitmapHandles.Remove(0);
            }
        iServer.iFreePrecacheBitmapHandles.Close();
        }
        if(res)
            {
            delete res;
            }
    }
    
// -----------------------------------------------------------------------------
// read each item from the list
// -----------------------------------------------------------------------------
TInt CAknIconSrvPrecacher::ReadPrecacheItemsL(TResourceReader& aReader)
    {
    TInt count = aReader.ReadInt16();
    if (count > 0)
        {
        User::LeaveIfError( iSkinSession.Connect( ) );
        
        CAknsSrvChunkLookup* lookup = iSkinSession.CreateChunkLookupL();
        CleanupStack::PushL( lookup );
        
        
        iCurrentFileName.Zero();
        
        
        for ( TInt i = 0 ; i < count ; i++ )
            {
#ifdef __AKNICON_TRACES
            RDebug::Printf("precache loop,%d,%d",i,count);
#endif
            
            TRAPD(error,ProcessEntryL(lookup, aReader));

            if(error != KErrNone)
                {
#ifdef __AKNICON_TRACES
                RDebug::Printf("Error Processing Precacher List");
#endif
                }

            }
            
        CleanupStack::PopAndDestroy( 1 ); // lookup
        iSkinSession.Close();
    
        }
    return count;
    }

// -----------------------------------------------------------------------------
// read each entry into iNewprecached items
// -----------------------------------------------------------------------------
void CAknIconSrvPrecacher::ProcessEntryL(CAknsSrvChunkLookup* lookup, TResourceReader& aReader)
    {
    TAknIconParams info;
    info.iRotationAngle = 0;
    info.iColor = KColorNotDefined;
    
    TFileName file;
        
    TInt skinIdMajor = aReader.ReadInt32();
    TInt skinIdMinor = aReader.ReadInt32();
    
    HBufC* temp;
    temp = aReader.ReadHBufC16L();
    
        
    if (temp)
        {
        file.Copy(temp->Des());
        delete temp;
        }
    else
        {
        file.Zero();
        }
    
    info.iBitmapId = aReader.ReadInt32();
    info.iMaskId = aReader.ReadInt32();
    TInt width = aReader.ReadInt32();
    TInt height = aReader.ReadInt32();
    info.iSize = TSize(width,height);
    info.iMode = (TScaleMode)aReader.ReadInt32();
    info.iAppIcon = EFalse;
    // Convert icon ID to MIF ID
    if ( info.iBitmapId >= KMifIdFirst )
        {
        info.iBitmapId -= KMifIdFirst;
        }
    if ( info.iMaskId >= KMifIdFirst )
        {
        info.iMaskId -= KMifIdFirst;
        }
        
    if (skinIdMajor != -1 || skinIdMinor != -1)
        {
        TAknsItemID id = { skinIdMajor, skinIdMinor };
        CAknsItemDef* def = lookup->LookupAndCreateDefL( id );
        if ( def )
            {
            CleanupStack::PushL( def );

            TAknsItemType type = def->Type();

            switch ( type )
                {
                case EAknsITBitmap:
                    {
                    info.iBitmapId=(*static_cast<CAknsBitmapItemDef*>( def )).Index();
                    if ( info.iBitmapId >= KMifIdFirst )
                        {
                        info.iBitmapId -= KMifIdFirst;
                        }
                    info.iMaskId = -1;
                    file = (*static_cast<CAknsBitmapItemDef*>( def )).Filename();
                    break;
                    }
                case EAknsITMaskedBitmap:
                    {
                    info.iBitmapId=(*static_cast<CAknsBitmapItemDef*>( def )).Index();
                    if ( info.iBitmapId >= KMifIdFirst )
                        {
                        info.iBitmapId -= KMifIdFirst;
                        }
                    info.iMaskId = info.iBitmapId + 1;

                    file = (*static_cast<CAknsBitmapItemDef*>( def )).Filename();
                    break;
                    }
                default:
                    {
                    break;
                    }
                }
            CleanupStack::PopAndDestroy(); // def
            }
        }
    if (file.Length() == 0)
        {
        #ifdef __AKNICON_TRACES
        RDebug::Printf("Precacher resource: File name invalid");
        #endif
        
        return;
        }

    if ( iCurrentFileName != file || iLoader == NULL )
        {
        delete iLoader;
        iLoader = NULL;
        iLoader = CAknIconLoader::NewL( iFs, file );
#ifdef _NGATESTING
        iLoader->SetIconTypeConfig(iServer.iConfigIconType, iServer.iNGADirectory);
#endif
        
        iCurrentFileName = file;
        }
    if( iLoader == NULL )
        {
        #ifdef __AKNICON_TRACES
        RDebug::Printf("Precacher resource: Unable to create iLoader");
        #endif
        
        return;
        }
    TPtrC8 iconData ;
    iconData.Set(iLoader->IconL( info.iBitmapId ));
    
    TDisplayMode bitmapDepth;
    bitmapDepth = (TDisplayMode)iLoader->IconDepthL( info.iBitmapId );
    
  /*  TDisplayMode maskDepth;
    maskDepth =  */(TDisplayMode)iLoader->MaskDepthL( info.iBitmapId );
    
    iSvgFormatHandler->SupportedDisplayMode(bitmapDepth, iServer.iIconMode );
 

    TInt iconHandle;
    
    iSvgFormatHandler->PrepareIconL( iconData, iconHandle );
    

    iLoader->FreeIcon();
    
    iSvgFormatHandler->UsePreparedIconL( iconHandle );
    
    
 
    CFbsBitmap* bitmap = new( ELeave ) CFbsBitmap;
    CleanupStack::PushL( bitmap );
    
    CFbsBitmap* mask = NULL;
    if ( info.iMaskId >= 0 )
        {
        mask = new( ELeave ) CFbsBitmap;
        CleanupStack::PushL( mask );
        }
        
    TAknContentDimensions dimensions;
     
    dimensions = AknIconSrvUtils::RenderPreparedIconL(
        *iSvgFormatHandler,
        bitmap,
        mask,
        bitmapDepth,
        iServer.IconDepth(),
        info.iSize,
        (TScaleMode)info.iMode,
        0 //RotationAngle 
        );
    
    
    
    iSvgFormatHandler->UnprepareIcon( iconHandle );
    
    //
    if (file.Left( KAknIconDefaultDirLength ) == KAknIconDefaultDir )
        {
        info.iFileName = file.Mid( KAknIconDefaultDirLength );
        info.SetDefaultIconDirUsed();
        }
    else
        {
        info.iFileName = file;
        }
    //
    CAknIconSrvIconItem* item;
    
    item = CAknIconSrvIconItem::NewL( info, bitmap, mask, dimensions, *(iServer.iFileNameCache ));
    CleanupStack::PushL(item);//item
    
    item->iUserCount--;
    
   if ( mask )
        {
        item->iUserCount--;
        }
   item->iPrecacheItem = ETrue;
   iServer.iNewPrecachedItems.AppendL(item);
   CleanupStack::Pop(); // item
   
   if ( mask )
        {
        CleanupStack::Pop(); // mask
        }
   CleanupStack::Pop(); //bitmap             
        
   }
   
HBufC8* CAknIconSrvPrecacher::SetupL()
    {
    RResourceFile file;
    file.OpenL( iFs, KAknIconResourceFile ) ;
    CleanupClosePushL( file );
    HBufC8* res =file.AllocReadLC( R_PRECACHE_LIST2 );
    CleanupStack::Pop(1); // res
    CleanupStack::PopAndDestroy(1);//file
    
    return res;
    
    }
    #endif
// ------------------------------EndOfFile-------------------------------------------
    
