//
//  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:   CriticalParameterTable.h
//
//  Project:    6046
//
//  Author(s):  W. Arcus
//
//  Purpose:    
//
//  Notes:      
//

#if !defined(AFX_CRITICALPARAMETERTABLE_H__F017085B_C697_4FF8_849C_4C76B882C530__INCLUDED_)
#define AFX_CRITICALPARAMETERTABLE_H__F017085B_C697_4FF8_849C_4C76B882C530__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "BaseThread.h"
#include "Swmrg.h"

#include <list>

#pragma warning( disable : 4663 )                                           // Microsoft's STL vector class is dirty, so disable warnings.
#pragma warning( disable : 4018 )
#include <vector>
#pragma warning( default : 4018 )
#pragma warning( default : 4663 )

typedef enum tagECRITICALPARAMETERID
{
    criticalParameterSoundSpeed,                                            // Sound speed                                  (m/s).
    criticalParameterVesselSpeed,                                           // Vessel speed                                 (m/s).
    criticalParameterAltitude,                                              // Altitude                                     (m).
    criticalParameterHeading,                                               // Heading                                      (rad).
    criticalParameterYaw,                                                   // Yaw                                          (rad).
    criticalParameterHeave,                                                 // Heave                                        (m).
    criticalParameterPitch,                                                 // Pitch                                        (rad).
    criticalParameterRoll,                                                  // Roll                                         (rad).

    criticalParameterPulseRepPeriod0,                                       // Trigger pulse rep. period for sensor index 0 (s).
    criticalParameterPulseRepPeriod1,
    criticalParameterPulseRepPeriod2,
    criticalParameterPulseRepPeriod3,
    criticalParameterPulseRepPeriod4,
    criticalParameterPulseRepPeriod5,
    criticalParameterPulseRepPeriod6,
    criticalParameterPulseRepPeriod7,
    criticalParameterPulseRepPeriod8,
    criticalParameterPulseRepPeriod9,
    criticalParameterPulseRepPeriod10,
    criticalParameterPulseRepPeriod11,
    criticalParameterPulseRepPeriod12,
    criticalParameterPulseRepPeriod13,
    criticalParameterPulseRepPeriod14,
    criticalParameterPulseRepPeriod15,                                      // Trigger pulse rep. period for sensor index 16 (s).

    // Insert new parameter id's before last entry to maintain an accurate count.

    criticalParameterMaxParameters                                          // Max number of critical parameters currently defined.
}
ECRITICALPARAMETERID;

#pragma pack( push, CRITICALPARAMETER_H_PACK, 1 )

typedef struct tagCRITICALPARAMENTRY                                        // Critical parameter table entry definition.
{
    unsigned long   m_ulParameterId;
    unsigned long   m_ulTimeStampOfUpdate;
    double          m_dValue;
}
CRITICALPARAMENTRY;

#pragma pack( pop, CRITICALPARAMETER_H_PACK )

// Client callback function definition.

typedef void ( * PFN_CRITICAL_PARAM_UPDATE )                                (   void                   *pvParam,            // Optional client parameter, typically a this pointer.
                                                                                int                     iSensorIndex,       // Sensor index to which this callback is addressed (from original subscription).
                                                                                unsigned long           ulTableSize,        // Number of parameters in the table.
                                                                                CRITICALPARAMENTRY     *psTable );          // Pointer to the critical parameter table.

#ifdef _DEBUG                                                               // CPar is a short-name alias for CCriticalParameterTable
#define CCriticalParameterTable CPar                                        // in debug mode. This is to suppress warning C4786 and to permit debugging.
#endif                                                                      // Yet another gem from Microsoft.

class EXPORT_DLL CCriticalParameterTable : protected CBaseThread
{
public:

    ///////////////
    // Definitions.

    typedef std::vector<ECRITICALPARAMETERID>   ParameterList_t;

    ///////////////
    // Services.

                                                CCriticalParameterTable     (   void );

    virtual                                    ~CCriticalParameterTable     (   void );

    bool                                        Subscribe                   (   const int                          &riSensorIndex,                          // Index of subscribing sensor.
                                                                                PFN_CRITICAL_PARAM_UPDATE           pfnCriticalParamCallback,               // Address of callback.
                                                                                void                               *pvParam                     = NULL,     // Optional callback parameter.
                                                                                ParameterList_t                    *pParameters                 = NULL );   // Optional parameter list, subscribe to all if not provied.

    bool                                        Unsubscribe                 (   const int                          &riSensorIndex );                        // Unsubscribes sensor from all parameters.

    bool                                        UpdateParameters            (   const unsigned long                &rulParametersToUpdate,
                                                                                const CRITICALPARAMENTRY           *psParameterEntry,
                                                                                const unsigned long                &rulTimeStamp );

protected:

    ///////////////
    // Definitions.

    typedef enum tagETHREADMESSAGES                                         // Recognised thread messages.
    {
        messageCriticalParamUpdate = threadMessageTerminate + 1             // The critical parameter table has been updated.
    }
    ETHREADMESSAGES;

    ///////////////
    // Services.

    void                                        WatchCycle                  (   void );
    BOOL                                        ProcessMessage              (   MSG                            *psMsg );

private:

    ///////////////
    // Definitions.

    class CSensorItem                                                       // Internal helper class to support client subscription linked list.
    {
    public:

        ///////////////
        // Services.

                                                CSensorItem                 (   const int                          &riSensorIndex,
                                                                                PFN_CRITICAL_PARAM_UPDATE           pfnCallback         = NULL,
                                                                                void                               *pvParam             = NULL );

                                                CSensorItem                 (   const CSensorItem                  &rRhs );

        virtual                                ~CSensorItem                 (   void );

        CSensorItem &                           operator =                  (   const CSensorItem                  &rRhs );

        bool                                    operator ==                 (   const int                          &riSensorIndex )     const;

        bool                                    operator <                  (   const CSensorItem                  &rRhs )              const;

        void                                    operator ()                 (   const unsigned long                &rulNumberOfParameterEntries,
                                                                                CRITICALPARAMENTRY  * const         psParamTable );

        void                                    Subscribe                   (   const bool                         &rbSubscribeAll,
                                                                                const ParameterList_t              *pParameters );

        int                                     SensorIndex                 (   void )                                              const;

        bool                                    QueueCallback               (   const unsigned long                &rulNumberOfUpdatedParameters,
                                                                                const CRITICALPARAMENTRY  *         psParamTable );

        void                                    CancelCallback              (   void );

        bool                                    IsCallbackQueued            (   void )  const;

    private:

        ///////////////
        // Attributes.

        int                                     m_iSensorIndex;
        PFN_CRITICAL_PARAM_UPDATE               m_pfnCallback;
        void                                   *m_pvParam;

        bool                                    m_bQueued;
        bool                                    m_bSubscribeAll;
        ParameterList_t                         m_SubscriptionIds;

        ///////////////
        // Services.
                                                CSensorItem                 (   void );             // Not implemented thus private to ensure non-use.

    };

    typedef std::list<CSensorItem>              SubscribingSensorList_t;
    typedef SubscribingSensorList_t::iterator   SubscribingSensorListIterator_t;

    ///////////////
    // Attributes.

    const int                                   m_iInvalidSensorIndex;
    const unsigned long                         m_ulNumberOfParameterEntries;
    const unsigned long                         m_ulPrimaryTableSizeInBytes;

    mutable CCritical                           m_ListGuard;
    mutable CSWMRG                              m_DataGuard;
    HANDLE                                      m_hTerminateEvent;

    static CRITICALPARAMENTRY                   m_asPrimaryTable     [ criticalParameterMaxParameters ];

    CRITICALPARAMENTRY                          m_asSecondaryTable   [ criticalParameterMaxParameters ];

    SubscribingSensorList_t                     m_SubscribingSensorList;

    ///////////////
    // Services.

    void                                        UpdateSubscribingClients    (   void );

    // Copy constructor and assignment operator not implemented thus private to ensure non-use.

                                                CCriticalParameterTable     (   const CCriticalParameterTable  &rRhs );           // Not implemented.
    CCriticalParameterTable &                   operator =                  (   const CCriticalParameterTable  &rRhs );           // Not implemented.

};

#endif // !defined(AFX_CRITICALPARAMETERTABLE_H__F017085B_C697_4FF8_849C_4C76B882C530__INCLUDED_)
