//
//  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:   MessageProcessor.h
//
//  Project:    6046
//
//  Author(s):  W. Arcus
//
//  Purpose:    
//
//  Notes:      
//

#if !defined(AFX_MESSAGEPROCESSOR_H__83F6854C_12D2_4BF4_A0F1_43386E946CF1__INCLUDED_)
#define AFX_MESSAGEPROCESSOR_H__83F6854C_12D2_4BF4_A0F1_43386E946CF1__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "..\..\..\Utils\NetUtils\Critical.h"
#include "..\..\..\Utils\NetUtils\DynamicBuffer.h"
#include "..\..\..\Utils\NetUtils\PLCSensorData.h"

class CPacketAssembler : public CCritical
{
public:

    ///////////////
    // Services.


                            CPacketAssembler            (   const unsigned long    &rulMaxPacketSize = 64UL * 1024UL,
                                                            const unsigned long    &rulMaxPackets    = 256UL );

    virtual                ~CPacketAssembler            (   void );

    void                    Reset                       (   void );

    void                    RemoveRecord                (   const unsigned long    &rulTransmissionId );

    bool                    Add                         (   const BYTE             *pby7kNetworkRecord,
                                                            const unsigned long    &rulPacketBytes,
                                                            const unsigned long    &rulTimestamp,
                                                            const int              &riSensorIndex );

    bool                    IsRecordComplete            (   unsigned long          &rulTransmissionId );

    bool                    RetrieveRecord              (   const unsigned long    &rulTransmissionId,
                                                            RECORDHEADER           &rsRecordHeader,
                                                            BYTE const *           &rpbyRecord,
                                                            unsigned long          &rulRecordBytes );

protected:

    ///////////////
    // Definitions.

#pragma pack( push, MESSAGE_PROCESSOR_H_PACK, 1 )

    typedef struct tagPACKETINFO
    {
        unsigned long           m_ulUsed;
        unsigned long           m_ulTransmissionIdentifier;
        unsigned long           m_ulSequenceNumber;
        unsigned long           m_ulSlotNumber;
        unsigned long           m_ulTimestamp;
        int                     m_iSensorIndex;
        char                    m_byReserved            [  8 ];

        static unsigned long Size( void )
        {
            return sizeof( struct tagPACKETINFO );
        }

        tagPACKETINFO( void )
        {
            memset( this, 0x00, tagPACKETINFO::Size() );
        }

        bool operator < ( const tagPACKETINFO &rRhs ) const
        {
            bool bIsLess = false;

            ASSERT( m_ulUsed != 0UL );

            if ( m_ulTransmissionIdentifier < rRhs.m_ulTransmissionIdentifier )
            {
                bIsLess = true;
            }
            else if ( m_ulTransmissionIdentifier == rRhs.m_ulTransmissionIdentifier )
            {
                bIsLess = ( m_ulSequenceNumber < rRhs.m_ulSequenceNumber );
            }

            return bIsLess;
        }

        bool operator == ( const tagPACKETINFO &rRhs ) const
        {
            return ( m_ulTransmissionIdentifier == rRhs.m_ulTransmissionIdentifier );
        }

    }
    PACKETINFO, *PPACKETINFO;

#pragma pack( pop, MESSAGE_PROCESSOR_H_PACK )

    typedef std::list<PACKETINFO>   PacketList_t;
    typedef PacketList_t::iterator  PacketListIterator_t;

    ///////////////
    // Attributes.

    const unsigned long             m_ulPacketSize;
    const unsigned long             m_ulMaxPackets;
    const unsigned long             m_ulPoolSize;

    unsigned long                   m_ulWriteSlotNumber;

    CDynamicBuffer<BYTE>            m_7kRecord;
    BYTE                           *m_pbyDataPool;

    PacketList_t                    m_PacketIndexTable;

    ///////////////
    // Services.

    BYTE *                          GetWriteSlot                    (   void );
    BYTE *                          GetSlot                         (   const unsigned long    &rulSlotNumber );

    void                            IncrementWritePoint             (   void );
    void                            RebuildPacketIndexInfo          (   void );

};

class CMessageProcessor : protected CPacketAssembler
{
public:

                                    CMessageProcessor               (   void );
    virtual                        ~CMessageProcessor               (   void );

    bool                            ValidateAndQueueRecord          (   const BYTE                 *pby7kRecord,
                                                                        const unsigned long        &rulBytes,
                                                                        const unsigned long        &rulTimestamp,
                                                                        const int                  &riSensorIndex );

private:

    //////////////
    // Attributes.

    bool                            m_bFirstFragment;

    int                             m_iBytes;

    unsigned long                   m_ulTimeStamp;
    unsigned long                   m_ulTimeOfFirstFragment;

    CPLCWriteSensorData             m_SensorDataPool;                                                       // Payload controller's shared sensor data pool.

    //////////////
    // Services.

    bool                            IsValid7kRecord                 (   const BYTE                 *pby7kRecord,
                                                                        const unsigned long        &rulBytes );

    unsigned long                   ComputeChecksum                 (   const unsigned char        *pucStream,
                                                                        const unsigned long        &rulStreamBytes );

    bool                            IsProtocolVersionCorrect        (   const BYTE                 *pby7kNetworkRecord,
                                                                        const unsigned long        &rulPacketBytes );

    bool                            IsPacketACompleteRecord         (   const BYTE                 *pby7kNetworkRecord,
                                                                        const unsigned long        &rulPacketBytes );

    bool                            WriteSingleRecord               (   const BYTE                 *pby7kNetworkRecord,
                                                                        const unsigned long        &rulPacketBytes,
                                                                        const unsigned long        &rulTimestamp,
                                                                        const int                  &riSensorIndex );

    bool                            WriteRecord                     (   const RECORDHEADER         &rsRecordHeader,
                                                                        const BYTE                 *pby7kRecord,
                                                                        const unsigned long        &rulRecordLength );

    bool                            WriteCompleteRecords            (   void );

                                    CMessageProcessor               (   const CMessageProcessor    &rRhs );         // Not implemented thus private.
    CMessageProcessor &             operator =                      (   const CMessageProcessor    &rRhs );         // Not implemented thus private.

};

#endif // !defined(AFX_MESSAGEPROCESSOR_H__83F6854C_12D2_4BF4_A0F1_43386E946CF1__INCLUDED_)
