//
//  Copyright © 2003, 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:   7kSharedMemoryInterface.cpp
//
//  Project:    6046
//
//  Author(s):  W. Arcus
//
//  Purpose:    
//
//  Notes:      
//

#include "StdAfx.h"
#include "7kSharedMemoryInterface.h"

#include "..\..\..\Utils\NetUtils\7kProtocol.h"

//////////////////////////////////////////////////////////////////////
// C7kSharedMemoryInterface class implementation.

using std::auto_ptr;

C7kSharedMemoryInterface::C7kSharedMemoryInterface( void )
                         :C7kSonarInterface()
{
    m_pToSonar   = auto_ptr<C7kInBoundMemory>( NULL );
    m_pFromSonar = auto_ptr<C7kOutBoundMemory>( NULL );
}

C7kSharedMemoryInterface::~C7kSharedMemoryInterface( void )
{
    if ( m_pToSonar.get() != NULL )
    {
        delete ( m_pToSonar.release() );
        m_pToSonar = auto_ptr<C7kInBoundMemory>( NULL );
    }

    if ( m_pFromSonar.get() != NULL )
    {
        delete ( m_pFromSonar.release() );
        m_pFromSonar = auto_ptr<C7kOutBoundMemory>( NULL );
    }
}

bool C7kSharedMemoryInterface::Connect( void )
{
    bool bSuccess = false;              // Assume failure for now.

    try
    {
        // Open the shared memory interfaces to the sonar in turn.

        m_pToSonar = auto_ptr<C7kInBoundMemory>( new C7kInBoundMemory );

        if ( m_pToSonar.get() == NULL )
        {
            ThrowMessage_m( "m_pToSonar is NULL" );
        }

        if ( ! m_pToSonar->Open() )
        {
            ThrowMessage_m( "Can't open 7k sonar inbound shared memory" );
        }

        m_pFromSonar = auto_ptr<C7kOutBoundMemory>( new C7kOutBoundMemory );

        if ( m_pFromSonar.get() ==  NULL )
        {
            ThrowMessage_m( "m_pFromSonar is NULL" );
        }

        if ( ! m_pFromSonar->Open() )
        {
            ThrowMessage_m( "Can't open 7k sonar outbound shared memory" );
        }

        bSuccess = true;
    }
    catch ( LPCTSTR lpszMessage )
    {
        bSuccess = false;
        TRACE( _T( "C7kSharedMemoryInterface::Connect(), %s.\n" ), lpszMessage );
    }
    catch ( ... )
    {
        bSuccess = false;
        TRACE( _T( "C7kSharedMemoryInterface::Connect(), Unspecified exception caught.\n" ) );
    }

    return bSuccess;
}

bool C7kSharedMemoryInterface::Disconnect( void )
{
    bool bSuccess = true;

    try
    {
        if ( m_pToSonar.get() != NULL )
        {
            delete ( m_pToSonar.release() );
            m_pToSonar = auto_ptr<C7kInBoundMemory>( NULL );
        }
    }
    catch ( ... )
    {
        bSuccess = false;
    }

    try
    {
        if ( m_pFromSonar.get() != NULL )
        {
            delete ( m_pFromSonar.release() );
            m_pFromSonar = auto_ptr<C7kOutBoundMemory>( NULL );
        }
    }
    catch ( ... )
    {
        bSuccess = false;
    }

    return ( ( m_pToSonar.get() == NULL ) && ( m_pFromSonar.get() == NULL ) );
}

bool C7kSharedMemoryInterface::Write7kRecord(   const BYTE          *pby7kRecord,
                                                const unsigned long &rulBytes )
{
    bool bSuccess = false;                  // Assume failure for now.

    try
    {
        ASSERT( C7kProtocol::IsValid7kRecord( pby7kRecord, rulBytes ) );

       // Write the record to the sonar's inbound memory area.

       ASSERT( m_pToSonar.get() != NULL );

       if ( ! m_pToSonar->Write( pby7kRecord, rulBytes ) )
       {
           ThrowMessage_m( "m_pToSonar->Write() failed" );
       }

        bSuccess = true;
    }
    catch ( LPCTSTR lpszMessage )
    {
        bSuccess = false;
        TRACE( _T( "C7kSharedMemoryInterface::Write(), %s.\n" ), lpszMessage );
    }
    catch ( ... )
    {
        bSuccess = false;
        TRACE( _T( "C7kSharedMemoryInterface::Write(), Unspecified exception caught.\n" ) );
    }

    return bSuccess;
}

C7kSharedMemoryInterface::operator HANDLE( void ) const
{
    ASSERT( m_pFromSonar.get() != NULL );

    return static_cast<HANDLE>( *(m_pFromSonar.get()));
}

bool C7kSharedMemoryInterface::HandleDataFromSonar( BYTE                *pby7kRecord,
                                                    unsigned long       &rulRecordBytes,
                                                    const unsigned long &rulMaxBufferSize,
                                                    const bool          &rbResetEvent )
{
    // Here, we use the m_pFromSonar object to retrieve (in a thread safe manner) a copy of the 
    // currently available 7k data record. We then parse, validate and handle the record.
    // Data record types are subsequently dispatched to subscribing clients via callback.

    bool bSuccess = true;

    rulRecordBytes = 0UL;

    if ( pby7kRecord == NULL )
    {
        bSuccess = false;
        TRACE( _T( "C7kSharedMemoryInterface::HandleDataFromSonar(), pby7kRecord is NULL.\n" ) );
    }
    else if ( m_pFromSonar.get() == NULL )
    {
        bSuccess = false;
        TRACE( _T( "C7kSharedMemoryInterface::HandleDataFromSonar(), pby7kRecord is NULL.\n" ) );
    }
    else
    {
        try
        {
            ASSERT( pby7kRecord        != NULL );
            ASSERT( m_pFromSonar.get() != NULL );

            unsigned long ulTimeStamp = 0UL;

            // While data records are available, retrieve a copy of each record and handle it appropriately.

            while ( m_pFromSonar->IsDataAvailable() )
            {
                if ( ! m_pFromSonar->Retrieve7kRecord( pby7kRecord, rulRecordBytes, ulTimeStamp, rulMaxBufferSize ) )
                {
                    bSuccess = false;
                    TRACE( _T( "C7kSharedMemoryInterface::HandleDataFromSonar(), m_pFromSonar->Retrieve7kRecord() failed" ) );
                    break;
                }

                if ( ! Handle7kRecordFromSonar( pby7kRecord, rulRecordBytes, ulTimeStamp ) )
                {
                    bSuccess = false;
                    TRACE( _T( "C7kSharedMemoryInterface::HandleDataFromSonar(), m_pFromSonar->Handle7kRecordFromSonar() failed" ) );
                    break;
                }
            }

            if ( rbResetEvent && ( ! m_pFromSonar->ResetEvent() ) )
            {
                TRACE( _T( "C7kSharedMemoryInterface::HandleDataFromSonar(), m_pFromSonar->ResetEvent() failed.\n" ) );
            }
        }
        catch ( LPCTSTR lpszMessage )
        {
            bSuccess = false;
            TRACE( _T( "C7kSharedMemoryInterface::HandleDataFromSonar(), %s.\n" ), lpszMessage );
        }
        catch ( ... )
        {
            bSuccess = false;
            TRACE( _T( "C7kSharedMemoryInterface::HandleDataFromSonar(), Unspecified exception caught!\n" ) );
        }
    }

    return bSuccess;
}



