//
//  Copyright © 2002, 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:   VehicleData.h
//
//  Project:    6046
//
//  Author(s):  W. Arcus
//
//  Purpose:    
//
//  Notes:      
//

#if !defined(AFX_VEHICLEDATA_H__ED483E88_13E0_44FD_B5BB_24F57C630297__INCLUDED_)
#define AFX_VEHICLEDATA_H__ED483E88_13E0_44FD_B5BB_24F57C630297__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "Sensor.h"

#include "..\..\..\Utils\NetUtils\7kProtocol.h"
#include "..\..\..\Utils\NetUtils\DynamicBuffer.h"
#include "..\..\..\Utils\NetUtils\Critical.h"
#include "..\..\..\Utils\NetUtils\BufferedData.h"
#include "..\..\..\Utils\NetUtils\PLCSensorData.h"
#include "..\..\..\Utils\NetUtils\UDPSocket.h"

#include "FrameQueue.h"
#include "BlueFinNetworkFrame.h"

#include <list>

#pragma warning( disable : 4663 )                           // Microsoft's STL vector class is dirty at warning level 4, so disable warnings.
#pragma warning( disable : 4018 )
#include <vector>
#pragma warning( default : 4018 )
#pragma warning( default : 4663 )

class CVehicleData;                                         // Forward definition.

class CSubscriber
{
public:

    // Private class of CVehicleData::CVehicle interface. Made external to suppress cause of warning C4786.
    // ... another gem from Microsoft.

    int             m_iSensorIndex;
    CVehicleData   *m_pParent;

    CSubscriber(    const int           &riSensorIndex = -1,
                    const CVehicleData *pParent        = NULL )
    {
        m_iSensorIndex = riSensorIndex;
        m_pParent      = const_cast<CVehicleData *>( pParent );
    }

    virtual ~CSubscriber( void )
    {
        m_iSensorIndex = -1;
        m_pParent      = NULL;
    }

    bool operator == ( const int &riSensorIndex ) const
    {
        return ( m_iSensorIndex == riSensorIndex );
    }

    bool operator <  ( const CSubscriber &rRhs ) const
    {
        return ( m_iSensorIndex < rRhs.m_iSensorIndex );
    }
};

class CVehicleData : public CSensor
{
public:

    ///////////////
    // Services.

                                CVehicleData                    (   const int                  &riSensorIndex   = -1 );

    virtual                    ~CVehicleData                    (   void );

    bool                        Configure                       (   const CString              &rAddress,
                                                                    const unsigned short       &runPort );

    bool                        Description                     (   unsigned long              &rulDeviceId,
                                                                    int                        &riSensorType,
                                                                    char                       *pszName )       const;

    void                        UpdateSensorHealth              (   void );

    // Overrides from abstract base class CSensor.

    bool                        Startup                         (   const int                  &riSensorIndex,
                                                                    const DWORD                &rdwThreadId,
                                                                    const unsigned int         &ruiDataReadyMessageId,
                                                                    const unsigned int         &ruiReplyReadyMessageId,
                                                                    const int                  &riActivateOnStartup );

    bool                        Shutdown                        (   void );

    bool                        Load                            (   BYTE                       *pbyData,
                                                                    unsigned long              *pulSize,
                                                                    unsigned long              *pulTimeStamp );

    bool                        SendCommand                     (   int                         iClientIndex,
                                                                    char                       *pszCommand );

    bool                        RetrieveStatus                  (   BYTE                       *pbyData,
                                                                    unsigned long              *pulSize,
                                                                    unsigned long              *pulTimeStamp,
                                                                    int                        *piClientIndex );


    bool                        IsSensorHealthy                 (   void );

    bool                        Reset                           (   void );

    bool                        RouteMessage                    (   const BYTE                 *pbyMessage,
                                                                    const unsigned long        &rulSize,
                                                                    const unsigned long        &rulTimeStamp );

    bool                        Identify                        (   SENSORINFO                 *psSensorInfo );

private:

    ///////////////
    // Definitions.

    class CVehicleInterface
    {
    public:

        //////////////
        // Services.

        explicit                CVehicleInterface               (   const unsigned short   &runPort );
        virtual                ~CVehicleInterface               (   void );

        bool                    Reset                           (   void );

        bool                    IsInitialized                   (   void )  const;

        bool                    Subscribe                       (   const CVehicleData     *pParent );

        bool                    UnSubscribe                     (   const int              &riSensorIndex );

        bool                    IsTimedOut                      (   void )  const;

    private:

        //////////////
        // Definitions.

        typedef std::list<CSubscriber>                          SubscriberList_t;
        typedef SubscriberList_t::iterator                      SubscriberListIterator_t;

        typedef std::vector<CRITICALPARAMENTRY>                 CriticalParameters_t;

        typedef CDynamicBuffer<BYTE>                            Buffer_t;

        typedef CDataCallback<PFN_DATACALLBACK>                 Callback_t;

        //////////////
        // Attributes.

        const unsigned long                                     m_ulMax7kRecordSize;
        const unsigned long                                     m_ulNavigationFramesPerRecord;
        const unsigned long                                     m_ulEnvironmentalFramesPerRecord;
        const unsigned long                                     m_ulDataTimeOut;

        bool                                                    m_bInitialized;

        unsigned short                                          m_unPort;

        unsigned long                                           m_ulTimeStampOfLastUpdate;

        SubscriberList_t                                        m_SubscriberList;

        std::auto_ptr<CUDPSocket>                               m_pSocketServer;
        std::auto_ptr<Buffer_t>                                 m_pRecord;

        CriticalParameters_t                                    m_CriticalParameters;

        CFrameQueue                                             m_NavigationFrameQueue;
        CFrameQueue                                             m_EnvironmentFrameQueue;

        mutable CCritical                                       m_FlagsCriticalSection;

        //////////////
        // Services.

        static bool             ReceiveHandler                  (   const void             *pvParam,
                                                                    const BYTE             *pbyData,
                                                                    const unsigned long    &rulBytes,
                                                                    const unsigned long    &rulTimeStamp );

        bool                    PreProcessAndDispatch           (   const BYTE             *pbyData,
                                                                    const unsigned long    &rulBytes,
                                                                    const unsigned long    &rulTimeStamp );

        bool                    NotifySubscribers               (   const BYTE             *pbyRecord,
                                                                    const unsigned long    &rulBytes,
                                                                    const unsigned long    &rulTimeStamp );

        bool                    FormatRecord                    (   const CFrameQueue      *pFrameQueue )       const;

        void                    SetDefaultHeader                (   RECORDHEADER7K         *psRecordHeader,
                                                                    const unsigned long    &rulTimeStamp )      const;

        bool                    UpdateCriticalParameterTable    (   const CBlueFinNetworkFrame &rFrame,
                                                                    const unsigned long        &rulTimeStamp );

                                CVehicleInterface               (   void );                                                 // Not implemented thus private.
                                CVehicleInterface               (   const CVehicleInterface &rRhs );                        // Not implemented thus private.
        CVehicleInterface &     operator =                      (   const CVehicleInterface &rRhs );                        // Not implemented thus private.

    };

    class CHealthStatus
    {
    public:

                                CHealthStatus                   (   void );
        virtual                ~CHealthStatus                   (   void );

        bool                    IsResponsive                    (   void ) const;

        bool                    UpdateStatus                    (   const bool                 &rbResponding,
                                                                    const bool                 &rbForceStatus = false );

    private:

        const int               m_iMinFailCount;
        const int               m_iMaxFailCount;

        mutable CCritical       m_StateGuard;

        bool                    m_bFailed;
        int                     m_iFailCount;

    };

    friend class                                                CVehicleInterface;                                          // Grant CVehicleInterface access to CVehicleData's protected and private members.

    ///////////////                                             
    // Attributes.                                              

    static std::auto_ptr<CVehicleInterface>                     m_pVehicleIF;                                               // Our one and only vehicle interface object.
    CPLCWriteSensorData                                         m_SensorDataPool;                                           // PLC's shared memory area.

    CString                                                     m_Address;
    unsigned short                                              m_unPort;

    CHealthStatus                                               m_HealthStatus;                                             // Subsystem health status object.

    ///////////////
    // Services.

    bool                        MessageHandler                  (   const BYTE                 *pby7kRecord,
                                                                    const unsigned long        &rulBytes,
                                                                    const unsigned long        &rulTimeStamp );

    void                        Disconnect                      (   void );

                                CVehicleData                    (   const CVehicleData         &rRhs );                     // Not implemented thus private.
    CVehicleData &              operator =                      (   const CVehicleData         &rRhs );                     // Not implemented thus private.

};

#endif // !defined(AFX_VEHICLEDATA_H__ED483E88_13E0_44FD_B5BB_24F57C630297__INCLUDED_)
