//
//  Copyright © 2004, RESON Inc. All Rights Reserved.
//
//  No part of this file may be reproduced or transmitted in any form or by
//  any means, electronic or mechanical, including photocopy, recording, or
//  information storage or retrieval system, without permission in writing
//  from RESON Inc.
//
//  Filename:   SensorList.h
//
//  Project:    6046
//
//  Author(s):  W. Arcus
//
//  Purpose:    Defines and implements a template class to manage the creation,
//              anhialation and access to sensor objects within a linked list.
//
//  Notes:      
//

#if !defined(AFX_SENSORLIST_H__5FE6BBF1_FFD5_4C03_8CFC_EEE44B703BDF__INCLUDED_)
#define AFX_SENSORLIST_H__5FE6BBF1_FFD5_4C03_8CFC_EEE44B703BDF__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#pragma warning( push, 3 )                                      // Microsoft's STL is dirty at warning level 4
#include <vector>
#include <list>
#pragma warning( pop )

#include "Critical.h"                                           // Critical section object.

///////////////////////////////////////////////////////////////////////////////
// CSensorList class definition.

template <class tSensor>
class CSensorList
{
public:

    ///////////////
    // Services.

    // Construction and destruction.

                            CSensorList             (   void );

    virtual                ~CSensorList             (   void );

    // Sensor management interface methods.

    tSensor *               AddSensor               (   const int              &riSensorIndex );

    tSensor *               GetSensor               (   const int              &riSensorIndex )     const;

    tSensor *               SensorFromSubsytemId    (   const int              &riSubsystemId )     const;

    bool                    RemoveSensor            (   const int              &riSensorIndex );

    bool                    RemoveAllSensors        (   void );

    std::vector<int>        GetSensorIndicies       (   void );

private:

    ///////////////
    // Definitions.

    typedef std::list<tSensor *>                SensorList_t;                           // Definition of our sensor object pointer linked list.
    typedef SensorList_t::iterator              SensorListIterator_t;                   // Iterator (smart pointer) for our sensor object pointer linked list.

    ///////////////
    // Attributes.

    mutable SensorList_t                        m_SensorList;                           // Linked list of sensors object pointers.
    mutable CCritical                           m_ListGuard;                            // Critical section for thread safe access of m_SensorList.

    ///////////////
    // Services.

    bool                    IsSensorInList          (   const int              &riSensorIndex ) const;

    bool                    Find                    (   SensorListIterator_t   &rpItem,
                                                        const int              &riSensorIndex ) const;

                            CSensorList             (   const CSensorList      &rRhs );              // Not implemented thus private.
    CSensorList &           operator =              (   const CSensorList      &rRhs );              // Not implemented thus private.

};

///////////////////////////////////////////////////////////////////////////////
// CSensorList class implementation.

template <class tSensor>
inline CSensorList<tSensor>::CSensorList( void )
{
    m_ListGuard.Enter();
    m_SensorList.clear();
    m_ListGuard.Leave();
}

template <class tSensor>
inline CSensorList<tSensor>::~CSensorList( void )
{
    try
    {
        if ( ! RemoveAllSensors() )
        {
            TRACE( _T( "CSensorList<tSensor>::~CSensorList(), failed\n" ) );
        }

        m_ListGuard.Enter();
        m_SensorList.clear();
        m_ListGuard.Leave();
    }
    catch ( ... )
    {
        TRACE( _T( "CSensorList<tSensor>::~CSensorList(), unspecified exception caught.\n" ) );
    }
}

template <class tSensor>
inline tSensor * CSensorList<tSensor>::AddSensor( const int &riSensorIndex )
{
    bool     bSuccess = false;
    tSensor *pSensor  = NULL;

    try
    {
        if ( ( pSensor = new tSensor( riSensorIndex ) ) == NULL )
        {
            ThrowMessage_m( "pSensor is NULL" );
        }

        m_ListGuard.Enter();
        m_SensorList.push_back( pSensor );
        m_ListGuard.Leave();

        TRACE( _T ( "CSensorList<tSensor>::AddSensor(), Added sensor %d to sensor list\n" ), riSensorIndex );

        bSuccess = true;
    }
    catch ( LPCTSTR lpszMessage )
    {
        bSuccess = false;
        TRACE( _T( "CSensorList<tSensor>::AddSensor(), %s\n" ), lpszMessage );
    }
    catch ( ... )
    {
        bSuccess = false;
        TRACE( _T( "CSensorList<tSensor>::AddSensor(), unspecified exception caught\n" ) );
    }

    if ( ( ! bSuccess ) && ( pSensor != NULL ) )
    {
        delete pSensor;
        pSensor = NULL;
        TRACE( _T( "CSensorList<tSensor>::AddSensor(), Sensor destroyed\n" ) );
    }

    return pSensor;
}

template <class tSensor>
inline tSensor * CSensorList<tSensor>::GetSensor( const int &riSensorIndex ) const
{
    tSensor *pSensor = NULL;

    m_ListGuard.Enter();

    if ( ! m_SensorList.empty() )
    {
        SensorListIterator_t pSensorItem;
        
        if ( Find( pSensorItem, riSensorIndex ) )
        {
            if ( pSensorItem != m_SensorList.end() )
            {
                pSensor = *pSensorItem;
            }
        }
    }

    m_ListGuard.Leave();

    return pSensor;
}

template <class tSensor>
inline tSensor * CSensorList<tSensor>::SensorFromSubsytemId( const int &riSubsystemId ) const
{
    tSensor *pSensor = NULL;

    m_ListGuard.Enter();

    if ( ! m_SensorList.empty() )
    {
        for ( SensorListIterator_t pSensorItem = m_SensorList.begin(); pSensorItem != m_SensorList.end(); pSensorItem++ )
        {
            if ( pSensorItem->m_pSensor->SubsystemId() == riSubsystemId )
            {
                pSensor = pSensorItem->m_pSensor;
                break;
            }
        }
    }

    m_ListGuard.Leave();

    return pSensor;
}

template <class tSensor>
inline bool CSensorList<tSensor>::RemoveSensor( const int &riSensorIndex )
{
    bool bSuccess = false;           // Assume failure for now.

    m_ListGuard.Enter();

    if ( ! m_SensorList.empty() )
    {
        SensorListIterator_t pSensorItem;
        
        if ( Find( pSensorItem, riSensorIndex ) )
        {
            if ( pSensorItem != m_SensorList.end() )
            {
                if ( pSensorItem != NULL )
                {
                    delete *pSensorItem;
                }

                m_SensorList.erase( pSensorItem );

                bSuccess = true;
            }
        }
    }
    m_ListGuard.Leave();

    return bSuccess;
}

template <class tSensor>
inline bool CSensorList<tSensor>::RemoveAllSensors( void )
{
    m_ListGuard.Enter();

    for ( SensorListIterator_t pSensorItem = m_SensorList.begin(); pSensorItem != m_SensorList.end(); pSensorItem++ )
    {
        if ( pSensorItem != NULL )
        {
            delete *pSensorItem;
            *pSensorItem = NULL;
        }
    }

    m_SensorList.clear();

    m_ListGuard.Leave();

    return true;
}

template <class tSensor>
inline std::vector<int> CSensorList<tSensor>::GetSensorIndicies( void )
{
    std::vector<int> IndexList;

    __TRY
    {
        m_ListGuard.Enter();

        for ( SensorListIterator_t pSensorItem = m_SensorList.begin(); pSensorItem != m_SensorList.end(); pSensorItem++ )
        {
            IndexList.push_back( (*pSensorItem)->SensorIndex() );
        }
    }
    __FINALLY
    {
        m_ListGuard.Leave();
    }
    __ENDFINALLY

    return IndexList;
}

/////////////////////////////////////////////////////////////////////////////
// Internal (private) helpers.

template <class tSensor>
inline bool CSensorList<tSensor>::Find( SensorListIterator_t &rpItem, const int &riSensorIndex ) const
{
    bool bFound = false;

    rpItem = m_SensorList.end();

    try
    {
        for ( SensorListIterator_t pSensorItem = m_SensorList.begin(); pSensorItem != m_SensorList.end(); pSensorItem++ )
        {
            if ( (*pSensorItem)->SensorIndex() == riSensorIndex )
            {
                rpItem = pSensorItem;
                bFound = true;
                break;
            }
        }
    }
    catch ( ... )
    {
        bFound = false;
        rpItem = m_SensorList.end();
    }

    return bFound;
}

#endif // !defined(AFX_SENSORLIST_H__5FE6BBF1_FFD5_4C03_8CFC_EEE44B703BDF__INCLUDED_)



