//
//  Copyright © 2002 - 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:   SensorInterface.cpp
//
//  Project:    6046
//
//  Author(s):  W. Arcus
//
//  Purpose:    Base class implementing common components in defining a 6046 
//              sensor module interface.
//
//  Notes:      
//

#include "StdAfx.h"
#include "SensorInterface.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// CSensorInterface static member initialization.

CSensorInterface *  CSensorInterface::m_pthis   = NULL;

//////////////////////////////////////////////////////////////////////
// CSensorInterface member implementation.

CSensorInterface::CSensorInterface( void )
{
    try
    {
        ASSERT( m_pthis == NULL );

        if ( m_pthis == NULL )
        {
            m_pthis = this;
        }

        m_bRetrievedSonarSettings   = false;
        m_iSensorRefCount           = 0;

        m_dVersion                  = 2.0000;

        m_pCriticalParameters       = NULL;
        m_pfnLogEvent               = NULL;
    }
    catch ( ... )
    {
        TRACE( _T( "CSensorInterface::CSensorInterface(), Unspecfied exception caught!\n" ) );
    }
}

CSensorInterface::~CSensorInterface( void )
{
    try
    {
        if ( m_pthis != NULL )
        {
            m_pthis = NULL;
        }

        m_bRetrievedSonarSettings   = false;
        m_iSensorRefCount           = 0;

        m_dVersion                  = 2.0000;

        m_pCriticalParameters       = NULL;
        m_pfnLogEvent               = NULL;
    }
    catch ( ... )
    {
        TRACE( _T( "CSensorInterface::~CSensorInterface(), Unspecfied exception caught!\n" ) );
    }
}

CSensorInterface * CSensorInterface::This( void )
{
    ASSERT( m_pthis != NULL );
    return m_pthis;
}

void CSensorInterface::HandleSubscribedCriticalParameterUpdate( const int                          &riSensorIndex,
                                                                const unsigned long                &rulTableSize,
                                                                const CRITICALPARAMENTRY * const    psTable )
{
    // Virtual method to be overridden, if necessary.

    UNREFERENCED_PARAMETER( riSensorIndex );
    UNREFERENCED_PARAMETER( rulTableSize );
    UNREFERENCED_PARAMETER( psTable );
}

double CSensorInterface::Version( void ) const
{
    return m_dVersion;
}

void CSensorInterface::Version( const double &rdVersion )
{
    m_dVersion = rdVersion;
}

void CSensorInterface::EventLog( void *pvfnLog )
{
    __ENTERCRITICAL( m_Critical )

    m_pfnLogEvent = reinterpret_cast<PFN_LOGEVENT>( pvfnLog );

    __LEAVECRITICAL( m_Critical )
}

void CSensorInterface::CriticalParameterTable( void *pvCriticalParameterTable )
{
    __ENTERCRITICAL( m_Critical )

    m_pCriticalParameters = reinterpret_cast<CCriticalParameterTable *>( pvCriticalParameterTable );

    __LEAVECRITICAL( m_Critical )
}

int CSensorInterface::AddSensorRef( void )
{
    int iSensorRefCount = 0;

    __ENTERCRITICAL( m_Critical )

    iSensorRefCount = ++m_iSensorRefCount;

    __LEAVECRITICAL( m_Critical )

    return iSensorRefCount;
}

int CSensorInterface::ReleaseSensorRef( void )
{
    int iSensorRefCount = 0;

    __ENTERCRITICAL( m_Critical )

    if ( --m_iSensorRefCount < 0 )
    {
        m_iSensorRefCount = 0;
    }

    iSensorRefCount = m_iSensorRefCount;

    __LEAVECRITICAL( m_Critical )

    return iSensorRefCount;
}

int CSensorInterface::SensorRefCount( void ) const
{
    int iSensorRefCount = 0;

    __ENTERCRITICAL( m_Critical )

    iSensorRefCount = m_iSensorRefCount;

    __LEAVECRITICAL( m_Critical )

    return iSensorRefCount;
}

bool CSensorInterface::LogEvent(    int     iEventType,
                                    int     iAction,
                                    int     iId,
                                    char   *pszFormat, ... )
{
    // Static public member providing access to the survey event log once sensor startup hase hegun and
    // both pthis and pthis->m_pfnLogEvent have been mapped by the host DLL.

    bool bSuccess = false;

    try
    {
        CSensorInterface *pthis = CSensorInterface::This();

        if ( pthis == NULL )
        {
            ThrowMessage_m( "pthis is NULL" );
        }

        pthis->m_Critical.Enter();

        try
        {
            if ( pthis->m_pfnLogEvent != NULL )
            {
                CString Message;
                va_list pArgumentList;

                va_start( pArgumentList, pszFormat );
                Message.FormatV( pszFormat,  pArgumentList );
                va_end( pArgumentList );

                if ( ! Message.IsEmpty() )
                {
                    bSuccess = ( ( pthis->m_pfnLogEvent )( iEventType, iAction, iId, const_cast<char *>(static_cast<LPCTSTR>( Message ) ) ) != 0 );
                }
            }
        }
        catch ( ... )
        {
            bSuccess = false;
        }

        pthis->m_Critical.Leave();
    }
    catch ( ... )
    {
        bSuccess = false;
    }

    return bSuccess;
}

bool CSensorInterface::SubscribeToCriticalParameters(   const int                                  &riSensorIndex,
                                                        CCriticalParameterTable::ParameterList_t   &rParameters )
{
    bool bSuccess = false;

    __ENTERCRITICAL( m_Critical )

    if ( m_pCriticalParameters != NULL )
    {
        bSuccess = m_pCriticalParameters->Subscribe( riSensorIndex, SubscribedCriticalParameterUpdate, this, &rParameters );
    }

    __LEAVECRITICAL( m_Critical )

    return bSuccess;
}

bool CSensorInterface::UnsubscribeFromCriticalParameters( const int &riSensorIndex )
{
    bool bSuccess = false;

    __ENTERCRITICAL( m_Critical )

    if ( m_pCriticalParameters != NULL )
    {
        bSuccess = m_pCriticalParameters->Unsubscribe( riSensorIndex );
    }

    __LEAVECRITICAL( m_Critical )

    return bSuccess;
}

bool CSensorInterface::UpdateCriticalParameters(    const unsigned long            &rulParametersToUpdate,
                                                    const CRITICALPARAMENTRY       *psParameterEntry,
                                                    const unsigned long            &rulTimeStamp )
{
    // Static public member providing access to the critical parameter update table once sensor startup has begun
    // and both pthis and pthis->m_pCriticalParameters have been mapped by the host DLL.

    bool bSuccess = false;

    CSensorInterface *pthis = CSensorInterface::This();

    ASSERT( pthis != NULL );
    
    if ( pthis != NULL )
    {
        if ( pthis->m_pCriticalParameters != NULL )
        {
            bSuccess = pthis->m_pCriticalParameters->UpdateParameters( rulParametersToUpdate, psParameterEntry, rulTimeStamp );
        }
    }

    return bSuccess;
}

void CSensorInterface::SubscribedCriticalParameterUpdate(   void               *pvParam,
                                                            int                 iSensorIndex,
                                                            unsigned long       ulTableSize,
                                                            CRITICALPARAMENTRY *psTable )
{
    try
    {
        CSensorInterface *pthis = reinterpret_cast<CSensorInterface *>( pvParam );

        if ( pthis == NULL )
        {
            TRACE( _T( "CSensorInterface::SubscribedCriticalParameterUpdate(), pthis is NULL!\n" ) );
        }
        else
        {
            pthis->HandleSubscribedCriticalParameterUpdate( iSensorIndex, ulTableSize, psTable );
        }
    }
    catch ( ... )
    {
        TRACE( _T( "CSensorInterface::SubscribedCriticalParameterUpdate(), Unspecified exception caught\n" ) );
    }
}

