//
//  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:   PLCSensorData.cpp
//
//  Project:    6046
//
//  Author(s):  W. Arcus
//
//  Purpose:    
//
//  Notes:      
//

#include "StdAfx.h"
#include "PLCSensorData.h"
#include "MMF6046.h"

///////////////////////////////////////////////////////////////////////////////
// Constants and definitions.

#define SharedMemory_m()        static_cast<CMMF6046 *>( m_pvSharedMemory )

///////////////////////////////////////////////////////////////////////////////
// CPLCSensorData class implementation.

CPLCSensorData::CPLCSensorData( void )
{
    ManageDllState_m();

    m_bInitialized   = false;
    m_pvSharedMemory = NULL;

    try
    {
        CMMF6046 *pMMF = new CMMF6046( _T( "RESON_6046_SENSORDATA_MEMMAP" ), false );

        if ( pMMF == NULL )
        {
            ThrowMessage_m( "Can't acquire 6046 shared memory pool" );
        }

        m_pvSharedMemory = static_cast<void *>( pMMF );
        m_bInitialized   = pMMF->IsInitialized();
    }
    catch ( LPCTSTR lpszMessage )
    {
        m_bInitialized = false;
        TRACE( _T( "CPLCSensorData::CPLCSensorData(), %s.\n" ), lpszMessage );
    }
    catch ( ... )
    {
        m_bInitialized = false;
        TRACE( _T( "CPLCSensorData::CPLCSensorData(), Unspecified exception caught.\n" ) );
    }
}

CPLCSensorData::~CPLCSensorData( void )
{
    ManageDllState_m();

    m_bInitialized = false;

    if ( m_pvSharedMemory != NULL )
    {
        delete ( SharedMemory_m() );
        m_pvSharedMemory = NULL;
    }
}

bool CPLCSensorData::IsInitialized( void ) const
{
    ManageDllState_m();

    return m_bInitialized;
}

bool CPLCSensorData::ResetMemoryPool( void )
{
    ManageDllState_m();

    ASSERT( m_bInitialized );

    CMMF6046 *pMMF = SharedMemory_m();
    ASSERT( pMMF != NULL );

    return pMMF->InitializeMMFContents();
}

///////////////////////////////////////////////////////////////////////////////
// CPLCWriteSensorData class implementation.

CPLCWriteSensorData::CPLCWriteSensorData( void )
                    :CPLCSensorData()
{
    ManageDllState_m();
}

CPLCWriteSensorData::~CPLCWriteSensorData( void )
{
    ManageDllState_m();
}

bool CPLCWriteSensorData::Write(    const RECORDHEADER     *psRecordHeader,
                                    const BYTE             *pbyRecord,
                                    const unsigned long    &rulTotalBytesThisRecord,
                                    const bool             &rbHiddenRecord )
{
    ManageDllState_m();

    bool bSuccess = false;      // Assume failure for now.

    try
    {
        ASSERT( m_bInitialized );

        CMMF6046 *pMMF = SharedMemory_m();
        ASSERT( pMMF != NULL );

        bSuccess = pMMF->Write( psRecordHeader, pbyRecord, rulTotalBytesThisRecord, rbHiddenRecord );
    }
    catch ( ... )
    {
        bSuccess = false;
        TRACE( _T( "CPLCWriteSensorData::Write(), Unspecified exception caught!\n" ) );
    }

    return bSuccess;
}

///////////////////////////////////////////////////////////////////////////////
// CPLCReadSensorData class implementation.

CPLCReadSensorData::CPLCReadSensorData( void )
                   :CPLCSensorData()
{
    ManageDllState_m();
}

CPLCReadSensorData::~CPLCReadSensorData( void )
{
    ManageDllState_m();
}

HANDLE CPLCReadSensorData::GetAvailableDataEvent( void )
{
    ManageDllState_m();

    ASSERT( m_bInitialized );

    CMMF6046 *pMMF = SharedMemory_m();
    ASSERT( pMMF != NULL );

    return pMMF->GetWriteEvent();
}

bool CPLCReadSensorData::Read(  unsigned long       &rulReadPoint,
                                BYTE                *pby7kRecord,
                                unsigned long       &rulBytes,
                                int                 &riSensorIndex,
                                unsigned long       &rulTimeStamp,
                                const unsigned long &rulMaxBufferSize,
                                bool                &rbHiddenRecord )
{
    ManageDllState_m();

    bool bSuccess = false;              // Assume failure for now.

    rulBytes        = 0UL;
    riSensorIndex   = 0UL;
    rulTimeStamp    = 0UL;
    rbHiddenRecord  = false;

    ASSERT( m_bInitialized );

    CMMF6046 *pMMF = SharedMemory_m();
    ASSERT( pMMF != NULL );

    CSWMRG *pGuard = pMMF->GetDataGuard();
    ASSERT( pGuard != NULL );

    try
    {
        unsigned long   ulTotalRecordBytes = 0UL;
        PRECORDHEADER   psRecordHeader     = NULL;

        pGuard->WaitToRead();

        if ( pMMF->Read( rulReadPoint, ulTotalRecordBytes, psRecordHeader, rbHiddenRecord ) )
        {
            if ( ulTotalRecordBytes == 0UL )
            {
                bSuccess = true;                    // Nothing to do.
            }
            else
            {
                const unsigned long ulRecordHeaderSize = sizeof( RECORDHEADER );
                const unsigned long ulRecordDataSize   = ulTotalRecordBytes - ulRecordHeaderSize;
                PBYTE               pbyRecordData      = ( reinterpret_cast<PBYTE>( psRecordHeader ) ) + ulRecordHeaderSize;

                if ( ( pbyRecordData    != NULL )             &&
                     ( pby7kRecord      != NULL )             &&
                     ( ulRecordDataSize <  rulMaxBufferSize )  )
                {
                    ::memcpy( pby7kRecord, pbyRecordData, ulRecordDataSize );

                    rulBytes      = ulRecordDataSize;
                    riSensorIndex = psRecordHeader->m_iSensorIndex;
                    rulTimeStamp  = psRecordHeader->m_ulMillisecondTimestamp;

                    bSuccess = true;
                }
            }
        }
    }
    catch ( ... )
    {
        bSuccess = false;
        TRACE( _T( "CPLCReadSensorData::Read(), Unspecified exception caught!\n" ) );
    }

    pGuard->DoneReading();

    return bSuccess;
}

CPLCReadSensorData::operator HANDLE ( void ) const
{
    ManageDllState_m();

    ASSERT( m_bInitialized );

    CMMF6046 *pMMF = SharedMemory_m();
    ASSERT( pMMF != NULL );

    HANDLE hWriteEvent = pMMF->GetWriteEvent();

    return hWriteEvent;
}

///////////////////////////////////////////////////////////////////////////////
// CPLCReadWriteSensorData class implementation.

CPLCReadWriteSensorData::CPLCReadWriteSensorData( void )
                        :CPLCWriteSensorData(),
                         CPLCReadSensorData()
{
    ManageDllState_m();

}

CPLCReadWriteSensorData::~CPLCReadWriteSensorData( void )
{
    ManageDllState_m();

}
