/*
* Copyright (c) 2005-2010 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:  CSysApBtSapController implementation
 *
*/


// INCLUDES

#include "SysApBtSapControllerImpl.h"
#include "SysApSubscriber.h"
#include "SysApAppUi.h"
#include <BTSapDomainPSKeys.h>
#include <btengdevman.h>
#include <btengconnman.h>
#include <StringLoader.h>
#include <coemain.h>
#include <SysAp.rsg>
#include <startupdomainpskeys.h>


MSysApBtSapController* CreateSysApBtSapControllerL( CSysApAppUi& aSysApAppUi )
    {
    return CSysApBtSapController::NewL( aSysApAppUi );
    }

// ============================ LOCAL FUNCTIONS ==============================
// -----------------------------------------------------------------------------
// SysApCBTDeviceArrayCleanup
// Cleanup operation for CBTDeviceArray
// -----------------------------------------------------------------------------
static void SysApCBTDeviceArrayCleanup( TAny* aItem )
    {
    CBTDeviceArray* devices = static_cast<CBTDeviceArray*>( aItem );
    devices->ResetAndDestroy();
    delete devices;
    }

// ============================ MEMBER FUNCTIONS ==============================

// ----------------------------------------------------------------------------
// CSysApBtSapController::NewL() 
// ----------------------------------------------------------------------------
CSysApBtSapController* CSysApBtSapController::NewL( CSysApAppUi& aSysApAppUi )
    {
    TRACES( RDebug::Print( _L("CSysApBtSapController::NewL") ) );
    CSysApBtSapController* self = new(ELeave) CSysApBtSapController( aSysApAppUi );
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop();
    return self;
    }

// ----------------------------------------------------------------------------
// CSysApBtSapController::CSysApBtSapController() 
// ----------------------------------------------------------------------------
CSysApBtSapController::CSysApBtSapController( CSysApAppUi& aSysApAppUi ) :
    iSysApAppUi( aSysApAppUi ),
    iBtSapEnabled( EFalse ),
    iSwitchingToOffline( EFalse )
    {
    }

// ----------------------------------------------------------------------------
// CSysApBtSapController::ConstructL() 
// ----------------------------------------------------------------------------
void CSysApBtSapController::ConstructL()
    {
    TRACES( RDebug::Print( _L("CSysApBtSapController::ConstructL") ) );
    iBtSapSubscriber = CSysApSubscriber::NewL( *this, KPSUidBluetoothSapConnectionState, KBTSapConnectionState );
    iBtSapSubscriber->Subscribe();
    }

// ----------------------------------------------------------------------------
// CSysApBtSapController::~CSysApBtSapController() 
// ----------------------------------------------------------------------------

CSysApBtSapController::~CSysApBtSapController()
    {
    TRACES( RDebug::Print( _L("CSysApBtSapController::~CSysApBtSapController") ) );
    delete iBtSapSubscriber;
    }

// ----------------------------------------------------------------------------
// CSysApBtSapController::BtSapEnabled()
// ----------------------------------------------------------------------------
TBool CSysApBtSapController::BtSapEnabled()
    {
    return iBtSapEnabled;
    }

// ----------------------------------------------------------------------------
// CSysApBtSapController::Disconnect()
// ----------------------------------------------------------------------------
TInt CSysApBtSapController::Disconnect()
    {
    TRACES( RDebug::Print( _L("CSysApBtSapController::Disconnect: iBtSapEnabled=%d"), iBtSapEnabled ) );

    RBTDevAddrArray addrArray;
    CBTEngConnMan* btConnMan = NULL;
    TRAPD( err, btConnMan = CBTEngConnMan::NewL() );
    if ( err == KErrNone )
        {
        err = btConnMan->GetConnectedAddresses( addrArray, EBTProfileSAP );
        if ( (err == KErrNone) && addrArray.Count() )
            {
            err = btConnMan->Disconnect( addrArray[0], EBTDiscGraceful );
            }
        else
            {
            TRACES( RDebug::Print( _L("CSysApBtSapController::Disconnect CBTEngConnMan::GetConnectedAddresses failed, err=%d"), err ) );
            }            
        }
    else
        {
        TRACES( RDebug::Print( _L("CSysApBtSapController::Disconnect CBTEngConnMan::NewL failed, err=%d"), err ) );
        }        
    delete btConnMan;
    addrArray.Close();
    
    return err;
    }

// ----------------------------------------------------------------------------
// CSysApBtSapController::SwitchingToOffline()
// ----------------------------------------------------------------------------
void CSysApBtSapController::SwitchingToOffline()
    {
    TRACES( RDebug::Print( _L("CSysApBtSapController:SwitchingToOffline") ) );
    iSwitchingToOffline = ETrue;
    }
    
// ----------------------------------------------------------------------------
// CSysApBtSapController::SimApplicationsClosed()
// ----------------------------------------------------------------------------
void CSysApBtSapController::SimApplicationsClosed()
    {
    TRACES( RDebug::Print( _L("CSysApBtSapController::SimApplicationsClosed()" ) ) );
    TInt err ( 0 );

    err = iSysApAppUi.SetStarterState( RStarterSession::EBTSap );

    if ( err )
        {
        TRACES( RDebug::Print( _L("CSysApBtSapController::SimApplicationsClosed SetMtcState( ESysApMtcBtSapState ) returns %d"), err ) );
        // We should end up in this branch only in the early integration phase of a product, and the
        // device is most likely dysfunctional after this error.
        }
    else
        {
        iFinalizeDisconnectNeeded = ETrue;
        
        // No RF available so signal bars should be same as in offline mode.
        iSysApAppUi.IgnoreZeroNetworkBarNotifications(ETrue);
        TRAP( err, iSysApAppUi.UpdateSignalBarsL( KAknSignalOffLineMode ) );

        iSysApAppUi.SetNetworkConnectionAllowed( ECoreAppUIsNetworkConnectionNotAllowed );

        // The SAP connection is accepted via P&S key
        RProperty::Set( KPSUidBluetoothSapConnectionState, KBTSapConnectionState, EBTSapAccepted );
        }
        
    TRACES( RDebug::Print( _L("CSysApBtSapController::SimApplicationsClosed() - END" ) ) );
    }

// ----------------------------------------------------------------------------
// CSysApBtSapController::FinalizeDisconnect()
// ----------------------------------------------------------------------------
void CSysApBtSapController::FinalizeDisconnect()
    {
    TRACES( RDebug::Print( _L("CSysApBtSapController::FinalizeDisconnect(): iSwitchingToOffline=%d"), iSwitchingToOffline ) );
    TInt err ( 0 );
    iFinalizeDisconnectNeeded = EFalse;
    iSysApAppUi.IgnoreZeroNetworkBarNotifications(EFalse);

    if ( iSysApAppUi.ActiveProfileId() == KOfflineModeProfileId )
        {
        if ( iSwitchingToOffline )
            {
            TRAP( err, iSysApAppUi.SwitchFromOnlineToOfflineModeL() );
            TRACES( RDebug::Print( _L("SwitchFromOnlineToOfflineModeL() leaves with err=%d"), err ) );
            iSwitchingToOffline = EFalse;
            }
        else
            {
            err = iSysApAppUi.SetStarterState( RStarterSession::EOffline );
            TRACES( RDebug::Print( _L("CSysApBtSapController::FinalizeDisconnect SetMtcState( ESysApNormalState ) returns %d"), err ) );
            }
        }
    else
        {
        err = iSysApAppUi.SetStarterState( RStarterSession::ENormal );
        
        if ( err == KErrNone )
            {
            iSysApAppUi.SetNetworkConnectionAllowed(ECoreAppUIsNetworkConnectionAllowed);
            }
        
        TRACES( RDebug::Print( _L("CSysApBtSapController::FinalizeDisconnect SetMtcState( ESysApNormalState ) returns %d"), err ) );
        }
    }

// ----------------------------------------------------------------------------
// CSysApBtSapController::HandlePropertyChangedL()
// ----------------------------------------------------------------------------
void CSysApBtSapController::HandlePropertyChangedL( const TUid& aCategory, const TUint aKey )
    {
    TInt simStatus = ESimStatusUninitialized;
    if ( aCategory == KPSUidBluetoothSapConnectionState && aKey == KBTSapConnectionState )
        {
        TInt value( 0 );
        RProperty::Get( aCategory, aKey, value );
        switch ( value )
            {
            case EBTSapNotConnected:
                TRACES( RDebug::Print( _L("CSysApBtSapController::HandlePropertyChangedL: EBTSapNotConnected, iFinalizeDisconnectNeeded=%d"), iFinalizeDisconnectNeeded ) );
                if ( iFinalizeDisconnectNeeded )
                    {
                    FinalizeDisconnect();
                    }
                iBtSapEnabled = EFalse;
                break;
            case EBTSapConnecting:
                TRACES( RDebug::Print( _L("CSysApBtSapController::HandlePropertyChangedL: EBTSapConnecting, iBtSapEnabled=%d"), iBtSapEnabled ) );
                //Ensure SIM is present
                simStatus = iSysApAppUi.StateOfProperty( KPSUidStartup, KPSSimStatus );
                if ( !iBtSapEnabled && !(simStatus == ESimNotPresent || simStatus == ESimNotSupported))
                    {
                    iSysApAppUi.InitCloseSimApplicationsL();
                    }
                break;
            case EBTSapConnected:
                TRACES( RDebug::Print( _L("CSysApBtSapController::HandlePropertyChangedL: EBTSapConnected") ) );
                iBtSapEnabled = ETrue;
                break;
            default:
                TRACES( RDebug::Print( _L("CSysApBtSapController::HandlePropertyChangedL: unhandled value: %d"), value ) );
                break;
            }
        }
    }


// ----------------------------------------------------------------------------
// CSysApBtSapController::GetBtSapDeviceNameL()
// ----------------------------------------------------------------------------
HBufC* CSysApBtSapController::GetBtSapDeviceNameL()
    {
    TRACES( RDebug::Print( _L("CSysApBtSapController::GetBtSapDeviceNameL()") ) );
    
    TBTDevAddr address;
    RBTDevAddrArray addrArray;
    CBTEngConnMan* btConnMan = NULL;
    TRAPD( err, btConnMan = CBTEngConnMan::NewL() );
    CleanupStack::PushL( btConnMan );
    if ( err == KErrNone )
        {
        err = btConnMan->GetConnectedAddresses( addrArray, EBTProfileSAP );
        if ( ( err == KErrNone ) && addrArray.Count() )
            {
            address = addrArray[0];
            }
        else if ( ( err == KErrNone) && !addrArray.Count() ) // not known whether this will ever occur
            {
            TRACES( RDebug::Print( _L("CSysApBtSapController::GetBtSapDeviceNameL:  CBTEngConnMan::GetConnectedAddresses() devices not found") ) );
            err = KErrNotFound; // discontinue name fetching
            }
        else
            {
            TRACES( RDebug::Print( _L("CSysApBtSapController::GetBtSapDeviceNameL:  CBTEngConnMan::GetConnectedAddresses() failed, err=%d"), err ) );
            }            
        }
    else
        {
        TRACES( RDebug::Print( _L("CSysApBtSapController::GetBtSapDeviceNameL:  CBTEngConnMan::NewL() failed, err=%d"), err ) );
        }        
    CleanupStack::PopAndDestroy( btConnMan );
    addrArray.Close();

    HBufC* prompt = NULL;

    if ( err == KErrNone )            
        {
        CBTEngDevMan* devMan = CBTEngDevMan::NewLC( NULL );
            
        TBTRegistrySearch criteria;
        criteria.FindAddress( address );
            
        CBTDeviceArray* devices = new (ELeave) CBTDeviceArray( 1 );
        CleanupStack::PushL( TCleanupItem( SysApCBTDeviceArrayCleanup, devices ) );
            
        err = devMan->GetDevices( criteria, devices );
            
        if ( err != KErrNone )
            {
            TRACES( RDebug::Print( _L("CSysApBtSapController::GetBtSapDeviceNameL CBTEngDevMan::GetDevices() returns %d"), err ) );
            }
        else
            {
            if ( devices->At( 0 )->IsValidFriendlyName() )
                {
                prompt = devices->At( 0 )->FriendlyName().AllocL();
                }
            else if ( devices->At( 0 )->IsValidDeviceName() )
                {
                prompt = (BTDeviceNameConverter::ToUnicodeL( devices->At( 0 )->DeviceName() ) ).AllocL();
                }    
            }        
            
        CleanupStack::PopAndDestroy( devices );
        CleanupStack::PopAndDestroy( devMan );
        }
    return prompt;        
    }

// End of File



