//  Copyright (c) 2001, Reson, Inc. All Rights Reserved.
//
//  Filename:   EdgeTechNetworkProtocol.cpp
//
//  Project:    6046
//
//  Author(s):  W. Arcus
//
//  Purpose:    
//
//  Notes:      
//

#include "StdAfx.h"
#include "EdgeTechHeaders.h"
#include "EdgeTechNetworkProtocol.h"

//////////////////////////////////////////////////////////////////////
// CEdgeTechNetworkProtocol class implementation starting with constructors
// and destructors.

CEdgeTechNetworkProtocol::CEdgeTechNetworkProtocol( void )
{
    m_pDecoder = std::auto_ptr<Buffer_t>( new Buffer_t );
    ASSERT( m_pDecoder.get() != NULL );

    m_pEncoder = std::auto_ptr<Buffer_t>( new Buffer_t );
    ASSERT( m_pEncoder.get() != NULL );

    if ( m_pEncoder.get() != NULL )
    {
        m_pEncoder->Reset();
    }

    if ( m_pDecoder.get() != NULL )
    {
        m_pDecoder->Reset();
    }
}

CEdgeTechNetworkProtocol::~CEdgeTechNetworkProtocol( void )
{
    DestroyAutoPointer( m_pEncoder );
    DestroyAutoPointer( m_pDecoder );
}

//////////////////////////////////////////////////////////////////////
// Services for decoding.

bool CEdgeTechNetworkProtocol::IsValidHeader(   BYTE                *pbyStream,
                                                const unsigned long &rulNumBytes )
{
    bool bValidHeader    = false;

    ASSERT( pbyStream   != NULL );
    ASSERT( rulNumBytes != NULL );

    if ( ( pbyStream != NULL ) && ( rulNumBytes >= GetHeaderSize() ) )
    {
        SonarMessageHeaderType *pHeader = reinterpret_cast<SonarMessageHeaderType *>( pbyStream );

        // Validate the header.

        bValidHeader = ( ( pHeader->startOfMessage >= SONAR_MESSAGE_HEADER_START     ) &&
                         ( pHeader->sonarMessage   >= SONAR_MESSAGE_NONE             ) &&
                         ( pHeader->byteCount      >= 0                              )  );
    }

    return bValidHeader;
}
                                                    
unsigned long CEdgeTechNetworkProtocol::GetHeaderSize( void )
{
    return sizeof( SonarMessageHeaderType );
}
                                                    
unsigned long CEdgeTechNetworkProtocol::BytesFollowingHeader( void ) const
{
    unsigned long ulBytesFollowingHeader = 0UL;

    ASSERT( m_pDecoder.get() != NULL );

    if ( m_pDecoder.get() != NULL )
    {
        BYTE *pbyStream       = m_pDecoder->GetAt( 0 );
        unsigned long ulBytes = m_pDecoder->Size();

        if ( IsValidHeader( pbyStream, ulBytes ) )
        {
            ulBytesFollowingHeader = (unsigned long) (reinterpret_cast<SonarMessageHeaderType *>( pbyStream ))->byteCount;
        }
    }

    return ulBytesFollowingHeader;
}
                                                    
bool CEdgeTechNetworkProtocol::IsRecordComplete( void ) const
{
    bool bRecordComplete = false;

    ASSERT( m_pDecoder.get() != NULL );

    if ( m_pDecoder.get() != NULL )
    {
        BYTE *pbyStream       = m_pDecoder->GetAt( 0 );
        unsigned long ulBytes = m_pDecoder->Size();

        if ( IsValidHeader( pbyStream, ulBytes ) )
        {
            bRecordComplete = ( (((unsigned long) (reinterpret_cast<SonarMessageHeaderType *>( pbyStream ))->byteCount ) + GetHeaderSize() ) <= ulBytes );
        }
    }

    return bRecordComplete;
}

bool CEdgeTechNetworkProtocol::ResetDecoder( void )
{
    bool bReset = false;

    ASSERT( m_pDecoder.get() != NULL );

    if ( m_pDecoder.get() != NULL )
    {
        m_pDecoder->Reset();
        bReset = true;
    }

    return bReset;
}

bool CEdgeTechNetworkProtocol::Add( BYTE                *pbyStream,
                                    const unsigned long &rulBytes,
                                    const bool          &rbIsHeader )
{
    // Here we add the bytes to the storage area but strip off any network header.
    // For the EdgTech, there isn't any so just stuff the bytes into the dynamic buffer.

    UNREFERENCED_PARAMETER( rbIsHeader );

    bool bSuccess = false;

    ASSERT( m_pDecoder.get() != NULL );
    ASSERT( pbyStream        != NULL );
    ASSERT( rulBytes         >  0UL  );

    if ( ( m_pDecoder.get() != NULL ) &&
         ( pbyStream        != NULL ) &&
         ( rulBytes         >  0UL  )  )
    {
        m_pDecoder->Add( pbyStream, rulBytes );
        bSuccess = true;
    }

    return bSuccess;
}

BYTE * CEdgeTechNetworkProtocol::DecodedRecord( void )
{
    ASSERT( m_pDecoder.get() != NULL );

    if ( m_pDecoder.get() != NULL )
    {
        return m_pDecoder->GetAt( 0 );
    }

    return NULL;
}

unsigned long CEdgeTechNetworkProtocol::DecodedRecordBytes( void )
{
    ASSERT( m_pDecoder.get() != NULL );

    if ( m_pDecoder.get() != NULL )
    {
        return ( sizeof( BYTE ) * m_pDecoder->Size() );
    }

    return 0UL;
}

//////////////////////////////////////////////////////////////////////
// Services for encoding.

bool CEdgeTechNetworkProtocol::EncodePackets(   BYTE           *pbyStream,
                                                unsigned long   ulNumBytes )
{
    bool bSuccess = false;

    ASSERT( m_pEncoder.get() != NULL );

    if ( m_pEncoder.get() != NULL )
    {
        m_pEncoder->Reset();

        if ( IsValidHeader( pbyStream, ulNumBytes ) )
        {
            m_pEncoder->Add( pbyStream, ulNumBytes );
            bSuccess = true;
        }
    }

    return bSuccess;
}

unsigned long CEdgeTechNetworkProtocol::GetNumberOfPackets( void )
{
    return 1UL;
}

BYTE * CEdgeTechNetworkProtocol::GetNextPacket( unsigned long &rulBytesInPacket )
{
    rulBytesInPacket = 0UL;

    BYTE *pbyPacket = NULL;

    ASSERT( m_pEncoder.get() != NULL );

    if ( m_pEncoder.get() != NULL )
    {
        rulBytesInPacket = sizeof( BYTE ) * m_pEncoder->Size();
        pbyPacket        = m_pEncoder->GetAt( 0 );
    }

    return pbyPacket;
}

