//
//  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:   7kSubsystem.h
//
//  Project:    6046
//
//  Author(s):  W. Arcus
//
//  Purpose:    
//
//  Notes:      
//

#if !defined(AFX_7KSUBSYSTEM_H__6ED7E6EF_B5D8_4118_B08D_3F485D0AC4B9__INCLUDED_)
#define AFX_7KSUBSYSTEM_H__6ED7E6EF_B5D8_4118_B08D_3F485D0AC4B9__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "Sensor.h"
#include "7kRemoteControl.h"
#include "SonarConfiguration.h"
#include "Singleton.h"
#include "Dispatcher.h"

#include "..\..\..\Utils\NetUtils\PLCSensorData.h"

#pragma warning( push, 3 )                                                                          // Microsoft's STL is dirty so suppress necessary warnings.
#pragma warning( disable : 4018 )
#include <vector>
#include <list>
#pragma warning( default : 4018 )
#pragma warning( pop )

//////////////////////////////////////////////////////////////////////
// C7kSubsystem class definition.

class C7kSubsystem : public CSensor
{
public:

    ////////////////////
    // Attributes.

    // Data collection modes -- bit masks that may be logically 'or'ed together to support multiple modes simultaneously.

    static const unsigned long          m_ulDataCollectionModeGenericSensors;                       // Generic sensors       -- record# 1000 to 1999.
    static const unsigned long          m_ulDataCollectionModeBeamData;                             // Beam data             -- record# 7008, 7000 to 7005.
    static const unsigned long          m_ulDataCollectionModeBathymetricData;                      // Bathymetric data      -- record# 7006, 7000 to 7005.
    static const unsigned long          m_ulDataCollectionModeBackscatteredImagery;                 // Backscattered imagery -- record# 7007, 7000 to 7005.

    ////////////////////
    // Services.

                                        C7kSubsystem                        (   const int                  &riSensorIndex = -1 );
    virtual                            ~C7kSubsystem                        (   void );

    bool                                IsInitialized                       (   void )                      const;

    bool                                SetDeviceIdInfo                     (   SENSORINFO const           *psSensorInfo );

    bool                                Description                         (   int                        &riSensorType,
                                                                                char                       *pszName );

    bool                                SetSystemTime                       (   const TIME7K               &rsTime7k,
                                                                                const unsigned long        &rulTimeStamp );

    void                                AutoShutdownMode                    (   const bool                 &rbAutoShutdown );

    unsigned long                       DataCollectionMode                  (   void )                      const;
    void                                DataCollectionMode                  (   const unsigned long        &rulDataCollectionMode );

    void                                ParameterRouting                    (   const bool                 &rbEnable );
    bool                                ParameterRouting                    (   void )  const;

    void                                MessageRouting                      (   const bool &rbEnable );
    bool                                MessageRouting                      (   void ) const;

    // Services to update survey data... used for beamforming and attitude correction.

    bool                                Roll                                (   const float                &rfRollInRadians );
    bool                                Pitch                               (   const float                &rfPitchInRadians );
    bool                                SoundSpeed                          (   const float                &rfSoundSpeedMetersInPerSecond );
    bool                                AbsorptionLoss                      (   const float                &rfAbsorptionLossIndBPerKilometer );
    bool                                SpreadingLoss                       (   const float                &rfSpreadingLossIndB );

    // Overrides from generic CSensor base class.

    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                       *pby7kRecord,
                                                                                unsigned long              *pulSize,
                                                                                unsigned long              *pulTimeStamp );

    bool                                SendCommand                         (   int                         iClientIndex,
                                                                                char                       *pszCommand );

    bool                                RetrieveStatus                      (   BYTE                       *pby7kRecord,
                                                                                unsigned long              *pulSize,
                                                                                unsigned long              *pulTimeStamp,
                                                                                int                        *piClientIndex );

    bool                                IsSensorHealthy                     (   void );

    bool                                Reset                               (   void );

    bool                                RouteMessage                        (   const int                  &riClientIndex,
                                                                                const BYTE                 *pbyMessage,
                                                                                const unsigned long        &rulSize,
                                                                                const unsigned long        &rulTimeStamp );

    bool                                Identify                            (   SENSORINFO                 *psSensorInfo );

    bool                                QueryHealth                         (   void );

    bool                                QueryIsAlive                        (   void );

private:

    ////////////////////
    // Definitions.

#pragma pack( push, SONAR7K_H_PACK, 1 )

    typedef struct tagCONFIGURATIONDATA                                                             // Configuration data stored and retrieved from disk on startup and shutdown.
    {
        float m_fPower;
        float m_fRange;
        float m_fGain;
        float m_fMaxPingRate;

        float m_fBottomDetectionMinRange;
        float m_fBottomDetectionMaxRange;
        float m_fBottomDetectionMinDepth;
        float m_fBottomDetectionMaxDepth;

        float m_fSoundSpeed;
        float m_fAbsorption;
        float m_fSpreadingLoss;

        bool                            SetDefault                          (   void );

    }
    CONFIGURATIONDATA, *PCONFIGURATIONDATA;

#pragma pack( pop, SONAR7K_H_PACK )

    class CClientReply
    {
    public:

        //////////////
        // Definitions.

        enum EREPLYID
        {
            replyIDNone                 = -1
        };

        //////////////
        // Attributes.

        int                             m_iClientIndex;
        EREPLYID                        m_eReplyId;

        //////////////
        // Methods.

                                        CClientReply                        (   const int                  &riClientIndex = -1,
                                                                                const EREPLYID             &reReplyId     = replyIDNone );

                                        CClientReply                        (   const CClientReply         &rRhs );
        CClientReply &                  operator =                          (   const CClientReply         &rRhs );

        virtual                        ~CClientReply                        (   void );

        bool                            operator ==                         (   const EREPLYID             &reReplyId ) const;
        bool                            IsValid                             (   void ) const;

    };

    class CAckNakReply
    {
    private:
    
        //////////////
        // Attributes.

        const unsigned long             m_ulStalePeriod;

    public:

        //////////////
        // Attributes.

        unsigned long                   m_ulRemoteControlId;
        unsigned long                   m_ulTicketNumber;
        GUID                            m_sUniqueId;
        unsigned long                   m_ulTimeStamp;
        int                             m_iClientIndex;

                                        CAckNakReply                        (   void );

                                        CAckNakReply                        (   const unsigned long        &rulRemoteControlId,
                                                                                const unsigned long        &rulTicketNumber,
                                                                                const GUID                 &rsUniqueId,
                                                                                const int                  &riClientIndex = -1 );

        virtual                        ~CAckNakReply                        (   void );

        bool                            operator ==                         (   const unsigned long        &rulTicketNumber )   const;

        bool                            operator <                          (   const CAckNakReply         &rRhs )              const;

        bool                            IsStale                             (   void ) const;

    };

    class CSonarCommands
    {
    public:

        /////////////
        // Services.

        typedef struct tagPARAMETERRANGES
        {
            float                       m_fMinRange;
            float                       m_fMaxRange;
            float                       m_fMinGain;
            float                       m_fMaxGain;
            float                       m_fMinPower;
            float                       m_fMaxPower;
            float                       m_fMinPulseLength;
            float                       m_fMaxPulseLength;
            float                       m_fMinPingRate;
            float                       m_fMaxPingRate;
        }
        PARAMETERRANGES, *PPARAMETERRANGES;

        /////////////
        // Services.

        // Object configuration.

                                        CSonarCommands                      (   void );
        virtual                        ~CSonarCommands                      (   void );

        bool                            ParameterRanges                     (   const CSystemInfo::DEVICEINFO  &rsDeviceInfo );
        PARAMETERRANGES                 ParameterRanges                     (   void )  const;

        bool                            SetParent                           (   C7kSubsystem * const            pSubsystem );

        // General sonar commands.

        bool                            QuerySonarSettings                  (   void );

        bool                            QuerySonarStaticSettings            (   void );

        bool                            QueryConfigSettings                 (   void );

        bool                            QuerySonarCapabilities              (   void );

        bool                            QuerySonarRemoteSettings            (   void );

        bool                            VolatileDataFeedSubscribe           (   void );

        bool                            QueryIsAlive                        (   void );

        bool                            PingEnable                          (   const bool                 &rbEnable );

        bool                            ShutdownSonar                       (   void );

        bool                            Reboot                              (   void );

        bool                            Calibrate                           (   void );

        bool                            Range                               (   const float                &rfRangeInMeters );

        bool                            MaxPingRate                         (   const float                &rfMaxPingsPerSecond );

        bool                            TransmitPower                       (   const float                &rfdBReOneMicroPascal );

        bool                            PulseWidth                          (   const float                &rfTxPulseWidthInSeconds );

        bool                            PulseType                           (   const unsigned long        &rulPulseType = 0 );

        bool                            ReceiverGain                        (   const float                &rfGainIndB );

        bool                            BottomDetectMethod                  (   const unsigned long        &rulBottomDetectMask );

        bool                            BottomDetectionFilterInfo           (   const float                &rfMinRange,
                                                                                const float                &rfMaxRange,
                                                                                const float                &rfMinDepth,
                                                                                const float                &rfMaxDepth );

        bool                            ProjectorSelection                  (   const unsigned long        &rulProjectorMagicNumber );

        bool                            ProjectorStabilization              (   const unsigned long        &rulProjectorMask );

        bool                            TransmitterStabilization            (   const unsigned long        &rulStabalizationMask );

        bool                            AutoRange                           (   const unsigned long        &rulAutoRangeMask );

        bool                            SelectHydroPhone                    (   const unsigned long        &rulHydroPhoneMagicNumber );

        bool                            ProjectorSteering                   (   const float                &rfSteeringAngleX,
                                                                                const float                &rfSteeringAngleY );

        bool                            ReceiverGainType                    (   const unsigned long        &rulReceiverGainType );

        bool                            TVGCoefficients                     (   void );

        bool                            AutoReceiverGain                    (   const unsigned long        &rulGainFlag );

        bool                            RequestSingleRecord                 (   const unsigned long        &rulRecordType,
                                                                                const unsigned long        &rulDeviceId,
                                                                                const unsigned short       &runEnumerator );

        bool                            VolatileDataFeed                    (   const unsigned long        &rulNumberOfRecords,
                                                                                const unsigned long        *paulRecordNumbers );

        bool                            VolatileDataFeed                    (   const unsigned long        &rulBeginRecordNumber,
                                                                                const unsigned long        &rulEndRecordNumber );

        bool                            LoadSystemDefaults                  (   void );

        bool                            LoadDeviceDefaults                  (   void );

        bool                            DisableVolatileDataFeed             (   void );

        bool                            PersistentDataFeed                  (   const bool                 &rbEnable,
                                                                                const unsigned long        &rulIPAddress           = 0,
                                                                                const unsigned short       &runPort                = 0,
                                                                                const unsigned short       &runProtocolFlag        = 0,
                                                                                const unsigned long        &rulNumberOfRecords     = 0,
                                                                                const unsigned long        *paulRecordNumbers      = NULL );

        // Services to update survey data; used for beamforming and attitude correction.

        bool                            Roll                                (   const float                &rfRollInRadians );
        bool                            Pitch                               (   const float                &rfPitchInRadians );
        bool                            SoundSpeed                          (   const float                &rfSoundSpeedMetersInPerSecond );
        bool                            AbsorptionLoss                      (   const float                &rfAbsorptionLossIndBPerKilometer );
        bool                            SpreadingLoss                       (   const float                &rfSpreadingLossIndB );

        // Overloads for sending a 7k formatted record.

        bool                            SendRecord                          (   const C7kRemoteControl     &rRemoteControlRecord );

        bool                            SendRecord                          (   const BYTE                 *pby7kRecord,
                                                                                const unsigned long        &rulBytes,
                                                                                const int                  &riClientIndex           = -1 );
        template <typename tRTH>
        bool                            SendRecord                          (   const CGeneric7kRecordEncoder<tRTH>    &rRecord );

    private:

        /////////////
        // Definitions.

        typedef struct tagCOMMAND
        {
            unsigned long               m_ulCommand;
            bool                        m_bSystemCommand;
        }
        COMMAND;

        /////////////
        // Attributes.

        const unsigned long             m_ulSystemDeviceId;
        const unsigned short            m_unSystemEnumerator;

        C7kSubsystem                   *m_pParent;                                                  // Pointer to the parent subsystem object.
        C7kRemoteControl                m_Command;                                                  // 7k remote control command (record 7500).
        CGeneric7kRecordEncoder<float>  m_DataRecord;                                               // 7k data update (various e.g., Pitch (7601) etc).

        PARAMETERRANGES                 m_sParamRanges;

        /////////////
        // Services.

        bool                            QueryMultipleSettings               (   const COMMAND * const       pasCommands,
                                                                                const unsigned int          uiNumberOfCommands );
    };

    class CConfigQuery : public CONFIGURATIONDATA
    {
    private:

        bool                            m_bSaveOnExit;
        bool                            m_bAccumulating;

        HANDLE                          m_hDoneEvent;

    public:

                                        CConfigQuery                        (   void );
        virtual                        ~CConfigQuery                        (   void );

        bool                            Configure                           (   void );
        void                            Release                             (   void );

        bool                            WaitForConfigReceived               (   const unsigned long        &rulTimeout );

        void                            SaveOnExit                          (   const bool                 &rbEnable );
        bool                            SaveOnExit                          (   void )  const;

        void                            DoneAccumulating                    (   void );
        bool                            IsAccumulating                      (   void )  const;

        void                            DecodeRecord                        (   const unsigned long        &rulRecordNumber,
                                                                                const BYTE                 *pby7kRecord,
                                                                                const unsigned long        &rulBytes );

                                        operator CONFIGURATIONDATA *        (   void );

    };

    class CHealthStatus
    {
    public:

                                        CHealthStatus                       (   void );
        virtual                        ~CHealthStatus                       (   void );

        bool                            IsResponsive                        (   void ) const;

        bool                            UpdateStatus                        (   const bool                 &rbResponding );

    private:

        const int                       m_iMinFailCount;
        const int                       m_iMaxFailCount;

        mutable CCritical               m_StateGuard;

        bool                            m_bFailed;
        int                             m_iFailCount;

    };

    // Grant internal helpers private access to C7kSubsystem.

    friend class CConfigQuery;
    friend class CSonarCommands;                                                                    // Grant CSonarCommands access to private members of its parent (C7kSubsystem).

    // Various STL-based list definitions et. al. and their iterators etc.

    typedef std::list<CClientReply>                 ClientReplyList_t;                              // Linked list messages to be sent to client sensors.
    typedef ClientReplyList_t::iterator             ClientReplyListIterator_t;
    typedef ClientReplyList_t::const_iterator       ClientReplyListConstIterator_t;

    typedef std::list<CAckNakReply>                 SonarReplyList_t;                               // List of sonar commands etc requiring reply etc (async processing).
    typedef SonarReplyList_t::iterator              SonarReplyListIterator_t;

    typedef CSonarConfiguration<CONFIGURATIONDATA>  Config_t;                                       // Sonar parameter class definition.

    ////////////////////
    // Attributes.

    bool                                m_bInitialized;                                             // Construction success.
    bool                                m_bAutoShutdown;                                            // Automatically shutdown the sonar when the last instance is destroyed.
    bool                                m_bParameterRouting;                                        // Flag permitting various system paramters to the sonar -- e.g., attitude data.
    bool                                m_bMessageRouting;                                          // Flag permitting passing inbound 7k records to the sonar.

    unsigned short                      m_unSystemEnumerator;                                       //  One of the 7k doublet identifiers.
    unsigned long                       m_ulDeviceId;                                               //  "   "  "   "    "         "

    unsigned long                       m_ulDataCollectionMode;                                     // Determines the sonar acoustic data record types to be collected.


    CCritical                           m_SonarCommandGuard;
    CSonarCommands                      m_SonarCommands;

    ClientReplyList_t                   m_ClientReplyList;

    CCritical                           m_SonarReplyListGuard;                                      // Critical section object for thread safe access to the reply list.
    SonarReplyList_t                    m_SonarReplyPendingList;                                    // List of pending sonar remote control replies (ACK/NAK).

    GUID                                m_sClientId;                                                // 128-bit id used for ACK/NAK tracing; we actually use a GUID.

    Config_t                            m_Config;                                                   // Configuration storage/retreival system object.
    CConfigQuery                        m_ConfigReadback;

    CPLCWriteSensorData                 m_SensorDataPool;                                           // Payload controller's shared sensor data pool.
    CSingleton<CDispatcher>             m_Dispatcher;                                               // Our one and only dispatcher object.

    CHealthStatus                       m_HealthStatus;                                             // Subsystem health status object.

    ///////////////
    // Services.

    CDispatcher *                       GetAndValidateDispatcher                (   void ) const;

    bool                                SetControlRanges                        (   void );

    bool                                NotifyHostOfReply                       (   const int                              &riClientIndex );

    bool                                SaveConfiguration                       (   void );
    bool                                RestoreConfiguration                    (   void );

    bool                                IsDataCollectionModeGenericSensors      (   void )  const;
    bool                                IsDataCollectionModeBeamData            (   void )  const;
    bool                                IsDataCollectionModeBathymetricData     (   void )  const;
    bool                                IsDataCollectionModeBackscatteredImagery(   void )  const;

    bool                                HandleSonarData                         (   const BYTE                             *pby7kRecord,
                                                                                    const unsigned long                    &rulBytes,
                                                                                    const unsigned long                    &rulTimeStamp,
                                                                                    const bool                             &rbSubsystemSpecificData );

    bool                                WriteToPLCSharedMemory                  (   const BYTE                             *pby7kRecord,
                                                                                    const unsigned long                    &rulBytes,
                                                                                    const unsigned long                    &rulTimeStamp );

    bool                                SubscribeToRecords                      (   const bool                             &rbEnable );

    bool                                HandleSystemEvent                       (   const unsigned long                    &rulRecordType,
                                                                                    const BYTE                             *pby7kRecord,
                                                                                    const unsigned long                    &rulBytes,
                                                                                    const unsigned long                    &rulTimeStamp );

    bool                                HandleTriggerMessages                   (   const unsigned long                    &rulRecordType,
                                                                                    const BYTE                             *pby7kRecord,
                                                                                    const unsigned long                    &rulBytes,
                                                                                    const unsigned long                    &rulTimeStamp );

    bool                                HandleTimeMessage                       (   const unsigned long                    &rulRecordType,
                                                                                    const BYTE                             *pby7kRecord,
                                                                                    const unsigned long                    &rulBytes,
                                                                                    const unsigned long                    &rulTimeStamp );

    void                                SetDefaultState                         (   void );

    TIME7K                              AgeTime                                 (   const TIME7K                           &rsTime7k,
                                                                                    const unsigned long                    &rulTimeStamp );

    bool                                WaitForRecord                           (   const unsigned long                    &rulRecordType,
                                                                                    const unsigned long                    &rulTimeout )    const;

    bool                                WaitForConfigurationFromSonar           (   const unsigned long                    &rulTimeout );

    bool                                IsRecordReceived                        (   const unsigned long                    &rulRecordType ) const;

    // ACK/NAK management services.

    bool                                QueueAckNakPending                      (   const BYTE                             *pby7kRecord,
                                                                                    const unsigned long                    &rulBytes,
                                                                                    const int                              &riClientIndex );


    bool                                HandleReceivedAckNak                    (   const unsigned long                    &rulRecordType,
                                                                                    const BYTE                             *pby7kRecord   );

    void                                MaintainPendingReplyList                (   void );

    void                                CommandFailed                           (   const CAckNakReply                     &rReply );

    void                                HandleNakReply                          (   const unsigned long                    &rulErrorCode,
                                                                                    const SonarReplyListIterator_t         &rpReply );

    void                                HandleAckReply                          (   const SonarReplyListIterator_t         &rpReply );

    void                                AckNakClient                            (   const CAckNakReply                     &rReply,
                                                                                    const bool                             &rbAck );

    bool                                ForceMandatoryState                     (   void );

    void                                SensorResponsive                        (   const bool                             &rbResponsive );

    // Callback handlers.

    static
    void                                DataReady                               (   const void                             *pvParam,
                                                                                    const BYTE                             *pby7kRecord,
                                                                                    const unsigned long                    &rulBytes,
                                                                                    const unsigned long                    &rulTimeStamp );

    static
    void                                GenericSensorDataReady                  (   const void                             *pvParam,
                                                                                    const BYTE                             *pby7kRecord,
                                                                                    const unsigned long                    &rulBytes,
                                                                                    const unsigned long                    &rulTimeStamp );

    // Copy constructor and assignment operator not implemented thus private.

                                        C7kSubsystem                            (   const C7kSubsystem                     &rRhs );                 // Not implemented thus private.
    C7kSubsystem &                      operator =                              (   const C7kSubsystem                     &rRhs );                 // Not implemented thus private.

};

#endif  // !defined(AFX_7KSUBSYSTEM_H__6ED7E6EF_B5D8_4118_B08D_3F485D0AC4B9__INCLUDED_)

