/*
 * Telefon.h
 *
 * Autor: Pawe Gala
 */

#ifndef TELEFON_H_
#define TELEFON_H_

#include <Etel3rdParty.h> 

class MTelefon
{
    public:
        virtual void NumerIMEI( TInt aBlad, const TDesC& aIMEI ) = 0;
};

class CTelefon : public CActive
{
    public:        // Konstruktory dwufazowe i destruktor
        static CTelefon* NewL();
        static CTelefon* NewLC();
        
        ~CTelefon();
        
    public:
        HBufC* PobierzIMEISyncL();
        void PobierzIMEIAsync( MTelefon* aTelefon );
        
    private:    // Wewntrzny enumerator
        enum TStan
        {
            EPobieranieSync = 1,
            EPobieranieAsync
        };
        
    private:    // Odziedziczone z CActive
        void DoCancel();
        void RunL();

    private:    // Konstruktory
        // - pierwsza faza
        CTelefon();
        // - druga faza
        void ConstructL();
        
    private:    // Pola
        MTelefon* iTelefonObserwer;
        TStan iStan;
        
        CTelephony* iTelefon;
        // Klasa TPhoneIdV1Pckg suy do zdeskryptoryzowania
        // obiektu klasy TPhoneIdV1.
        CTelephony::TPhoneIdV1 iIdentyfikator;
        CTelephony::TPhoneIdV1Pckg iIdentyfikatorPckg;
};

#endif /* TELEFON_H_ */

/*
 * Telefon.cpp
 *
 * Autor: Pawe Gala
 */

#include "Telefon.h"

CTelefon* CTelefon::NewL()
{
    CTelefon* self = CTelefon::NewLC();
    CleanupStack::Pop( self );
    return self;
}

CTelefon* CTelefon::NewLC()
{
    CTelefon* self = new( ELeave ) CTelefon();
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;
}

CTelefon::CTelefon()
:CActive( EPriorityStandard )
,iIdentyfikatorPckg( iIdentyfikator )
{
    CActiveScheduler::Add( this );
}

CTelefon::~CTelefon()
{
    Cancel();
    delete iTelefon;
}

void CTelefon::ConstructL()
{
    iTelefon = CTelephony::NewL();
}

HBufC* CTelefon::PobierzIMEISyncL()
{
    iStan = EPobieranieSync;
    
    // Starujemy asynchroniczn usug pobierania numeru IMEI urzdzenia.
    Cancel();
    iTelefon->GetPhoneId( iStatus, iIdentyfikatorPckg );
    SetActive();
    // Uruchamiamy drug niezalen ptl Zarzdcy Aktywnoci.
    CActiveScheduler::Start();
    
    // Tutaj znajdziemy si dopiero po wywoaniu metody CActiveScheduler::Stop()
    // w metodzie CTelefon::RunL().
    HBufC* imsi = NULL;
    
    if( iStatus.Int() == KErrNone )
    {
        // Numer IMEI zosta pobrany pomylnie.
        imsi = iIdentyfikator.iSerialNumber.AllocL();
    }
    
    return imsi;
}

void CTelefon::PobierzIMEIAsync( MTelefon* aTelefon )
{
    __ASSERT_ALWAYS( aTelefon != NULL, User::Leave( KErrArgument ) );
    iTelefonObserwer = aTelefon;
    
    iStan = EPobieranieAsync;
    
    Cancel();
    iTelefon->GetPhoneId( iStatus, iIdentyfikatorPckg );
    SetActive();
}

void CTelefon::DoCancel()
{
    iTelefon->CancelAsync( CTelephony::EGetPhoneIdCancel );
}

void CTelefon::RunL()
{
    // Usuga asynchronicznego pobierania numeru IMEI zostaa wykonana.
    
    if( iStan == EPobieranieSync )
    {
        // Zatrzymujemy zagniedon ptl Zarzdcy Aktywnoci - pozwlmy
        // metodzie PobierzIMEISyncL() wykona si do koca. Naley zaznaczy,
        // e sterowanie wrci do metody PobierzIMEISyncL() dopiero po wykonaniu
        // biecej metody RunL().
        CActiveScheduler::Stop();
    }
    else if( iStan == EPobieranieAsync )
    {
        iTelefonObserwer->NumerIMEI( iStatus.Int(), iIdentyfikator.iSerialNumber );
    }
    else
    {
        // Obiekt znajduje si w niezdefiniowanym stanie.
        _LIT( KKategoriaPaniki, "CTelefon" );
        const TInt KNumerPaniki = 1;
        User::Panic( KKategoriaPaniki, KNumerPaniki );
    }
}

// ----------------
// Uycie klasy CTelefon
// ----------------
iTelefon = CTelefon::NewL();
// Synchroniczne pobranie numeru IMEI
HBufC* imsi = iTelefon->PobierzIMEISyncL();
// imsi = "000000000000000" (warto uzyskana na emulatorze)
delete imsi;

// Asynchroniczne pobranie numeru IMEI
// Numer zostanie dostarczony przez wywoanie metody this::NumerIMEI().
iTelefon->PobierzIMEIAsync( this );
