//
//  Copyright © 2001 - 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:   Subsystem.h
//
//  Project:    6046
//
//  Author(s):  W. Arcus
//
//  Purpose:    
//
//  Notes:      
//

#if !defined(AFX_SUBSYSTEM_H__7CFA7542_2EF7_47BA_B29B_F587CFF0D622__INCLUDED_)
#define AFX_SUBSYSTEM_H__7CFA7542_2EF7_47BA_B29B_F587CFF0D622__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "EdgeTechMessage.h"

#include "..\..\..\Utils\NetUtils\SWMRG.h"
#include "..\..\..\Utils\NetUtils\Critical.h"
#include "..\..\..\Utils\NetUtils\7kProtocol.h"
#include "..\..\..\Utils\NetUtils\PLCSensorData.h"

#include "ChannelSequencer.h"
#include "SubsystemConfig.h"

// Forward definitions

class CCommandProcessor;    
class CDataProcessor;

class CSubsystem
{
public:

    ///////////////
    // Definitions

    enum ESUBSYSTEMTYPE
    {
        subsystemUnknown    = -1,
        subsystemSSSLF,
        subsystemSSSHF,
        subsystemSBP,

        maxSubsystemTypes
    };

    enum NOTIFYTYPE
    {
        notifyStatusUpdate   = 0,
        notifyPingUpdate,
        notifyTimeout,
        notifyDroppedPing
    };

    enum ESTATUSUPDATE
    {
        statusUpdateNone                        = -1,
        statusUpdateMessageNone,
        statusUpdateSystemVersion,
        statusUpdateDataNetworkWindow,
        statusUpdateDataActive,
        statusUpdateEnhanceWindow,
        statusUpdateProcessingDirectPath,
        statusUpdatePing,
        statusUpdatePingGain,
        statusUpdatePingList,
        statusUpdatePingSelect,
        statusUpdatePingRate,
        statusUpdatePingTrigger,
        statusUpdatePingDelay,
        statusUpdatePingMaxSamples,
        statusUpdatePingRange,
        statusUpdatePingCouplingParameters,
        statusUpdatePingFishList,
        statusUpdateADCGain,
        statusUpdateADCAGC,
        statusUpdateADCRate
    };

    enum EREPLYTYPE
    {
        replyPingList
    };

    enum ESHUTDOWNTYPE
    {
        shutdownTypeSonarProgram        = 0,
        shutdownTypeOSShutdown,
        shutdownTypeOSReboot
    };

    typedef struct tagSUBSYSTEMIDTABLEENTRY
    {
        ESUBSYSTEMTYPE  m_eType;
        char            m_szKey         [ _MAX_PATH ];
        DWORD           m_dwSubsystemId;
    }
    SUBSYSTEMIDTABLEENTRY;

    ///////////////
    // Services.

    // Construction and destruction.

                    CSubsystem              (   CCommandProcessor       *pSonarCommandProcessor = NULL,
                                                CDataProcessor          *pSonarDataProcessor    = NULL );

    virtual        ~CSubsystem              (   void );

    bool            IsInitialized           (   void ) const;

    // Subsystem id access.

    int             SubsystemId             (   void ) const;
    void            SubsystemId             (   const int                   &riId );

    ESUBSYSTEMTYPE  SubsystemType           (   void ) const;
    void            SubsystemType           (   const ESUBSYSTEMTYPE        &reSubsystemType );

    void            EnableAutoShutdown      (   const   bool                &rbEnable );

    // Data ready helpers - invoked on callback from respective message processors.

    bool            HandleSonarData         (   const CEdgeTechMessage      &rMessage,
                                                const unsigned long         &rulTimeStamp );

	bool            HandleSonarCommand      (   const CEdgeTechMessage      &rMessage,
                                                const unsigned long         &rulTimeStamp );

    bool            ReInitializeSubsystem   (   CCommandProcessor           *pSonarCommandProcessor,
                                                CDataProcessor              *pSonarDataProcessor );

    int             SensorIndex             (   void )  const;

protected:

    ///////////////
    // Attributes.

    CCommandProcessor                      *m_pSonarCommandProcessor;           // Sonar command processor object.
    CDataProcessor                         *m_pSonarDataProcessor;              // Sonar data processor object.

    int                                     m_iSensorIndex;

    mutable CCritical                       m_StateDataGuard;                   // Critical section to guard muti-threaded access to state state data.
    CCritical                               m_StatusQueueGuard;                 // Multi-threaded data guard for queued 7k status records.

//  CCritical                               m_DataGuard;                        // Multi-threaded data guard for queued 7k data records.
//  CBufferedData<QUEUEDMESSAGE>            m_DataRecordQueue;                  // 7k record queue.
    CBufferedData<QUEUEDMESSAGE>            m_StatusQueue;                      // Status, reply and alarm message queue.

    ///////////////
    // Services.

    bool            SetSystemParameters     (   const int                   &riSubsystemId,
                                                const int                   &riSensorIndex,
                                                const DWORD                 &rdwThreadId,
                                                const unsigned int          &ruiDataReadyMessageId,
                                                const unsigned int          &ruiReplyReadyMessageId );

    bool            InitializeSubsystem     (   const bool                  &rbActivateOnStart,
                                                const bool                  &rbKeepActivationState = true );

    virtual
    bool            SetSystemTime           (   void );

    bool            Shutdown                (   void );

    void            ShutdownSonar           (   const ESHUTDOWNTYPE        &reShutdownType );

    long            IdOfSubsystemType       (   const ESUBSYSTEMTYPE       &reSubsystemType ) const;

    bool            IsHealthy               (   void )  const;

    void            SetRxGain               (   int                         iRxGain,
                                                const bool                 &rbUpdateConfig );

    void            SetTxPower              (   const float                &rfTxPower,
                                                const bool                 &rbUpdateConfig );

    void            SetPingDuration         (   const float                &rfPingDuration,
                                                const bool                 &rbUpdateConfig );

    void            EnableAGC               (   bool                        bEnable );

    void            PingEnable              (   bool                        bEnable,
                                                const bool                 &rbUpdateConfig );

    void            PingOnce                (   void );

    void            SetPulseFile            (   const CString               &rPulseFileName,
                                                const bool                  &rbUpdateConfig );

    void            SetRange                (   float                       fRange,
                                                const bool                  &rbUpdateConfig );

    void            SetTriggerMode          (   const long                  &rlTriggerMode );

    void            SetTriggerModeProperties(   const long                  &rlTriggerMode,
                                                long                        lDelayInMicroseconds,
                                                long                        lCoupledSubsystemIndex,
                                                long                        lEventsToTriggerOn );

    void            EnablePingDataTxOnSonarChannel( const bool              &rbEnable );

    void            Sleep                   (   const   DWORD               &rdwWaitPeriodInMilliseconds,
                                                bool                        bBlockThread = true );

    void            QueryPulseFileListQuery (   void );

    void            RetrievePulseFileListQuery( int                         iClientIndex );

    void            SetDefaultState         (   void );

private:

    ///////////////
    // Definitions.

#pragma pack( push, SUBSYSTEM_H_PACK, 1 )

    typedef struct tagSTATUS
    {
        bool                                    m_bDataActive;

        long                                    m_lTestMessageCounter;
        long                                    m_lDirectPathHoldoff;
        long                                    m_lPingEnable;
        long                                    m_lPingGain;
        long                                    m_lPingRate;
        long                                    m_lTriggerMode;
        long                                    m_lExternalSoftTriggerDelay;
        long                                    m_lMaxSamplesPossible;
        long                                    m_lRangeInMillimeters;
        long                                    m_lADCGain;
        long                                    m_lADCAGC;
        long                                    m_lADCRate;

        unsigned long                           m_ulTimestampOfLastStatusUpdate;
        unsigned long                           m_ulNumPulses;

        char                                    m_szVersion         [ ulMaxVersionStringLength_c ];
        char                                    m_szSelectedPulse   [ ulMaxPulseFileNameLength_c ];

        SonarMessageWindowType                  m_sDataNetworkWindow;
        SonarMessageWindowType                  m_sEnhanceWindow;
        SonarMessageCouplingParametersType      m_sCouplingParameters;

        SonarMessagePingType                    m_asPulseFile       [ ulMaxPulseFiles_c ];
        SonarMessageFishType                    m_asFishType        [ ulMaxFishTypes_c ];

                        tagSTATUS   (   void );
        virtual        ~tagSTATUS   (   void );
        void            Reset       (   void );
        static size_t   Size        (   void );
    }
    STATUS;

#pragma pack( pop, SUBSYSTEM_H_PACK )

    ///////////////
    // Attributes.

    const int                               m_iInvalidSubsystemId;
    const DWORD                             m_dwInvalidThreadId;
    const unsigned long                     m_ulMaxPingSize;
    const unsigned long                     m_ulMaxFishTypes;
    const unsigned long                     m_ulMaxPulseFiles;
    const float                             m_fVersionSupportingOSShutdown;

    static bool                             m_bIdTableLoaded;
    static bool                             m_bAutoShutdownOS;
    static int                              m_iRefCount;
    static SUBSYSTEMIDTABLEENTRY            m_sSubsystemIdTable[ maxSubsystemTypes ];

    bool                                    m_bInitialized;
    bool                                    m_bActivateOnStart;
    ESUBSYSTEMTYPE                          m_eSubsystemType;

    int                                     m_iSubsystemId;
    int                                     m_iDataChannels;

    DWORD                                   m_dwThreadId;
    UINT                                    m_uiDataReadyMessageId;
    UINT                                    m_uiReplyReadyMessageId;

    bool                                    m_bPulseFileListRecieved;
    bool                                    m_bPulseFileListReplyRequested;
    int                                     m_iReplyClientIndex;

    CChannelSequencer                       m_ChannelSequencer;
    CPLCWriteSensorData                     m_SensorDataPool;

    BYTE                                   *m_pby7kRecord;

    STATUS                                  m_sStatus;
    CSubsystemConfig                        m_Config;

    float                                   m_fSoftwareVersion;

    ///////////////
    // Services.

    bool            LoadConfiguration       (   void );

    bool            SaveConfiguration       (   void );


    bool            SendCommand             (   unsigned short              unMessage,
                                                unsigned char               ucCommand        = SONAR_COMMAND_GET,
                                                BYTE                        *pbyMessage       = NULL,
                                                unsigned long               ulBytesInMessage = 0,
                                                unsigned char               ucChannel        = 0,
                                                int                         iSubsystemId     = -1 );

    ESUBSYSTEMTYPE  TypeFromId              (   const int                   &riSubsystemId );

    void            LoadIdTable             (   void ) const;

    CString         PulseFileFromDescription(   const CString               &rPulseDescription );

    void            Reset                   (   void );
                                            
    void            QueryCommonSettings     (   void );
                                            
    void            QueryAliveStatus        (   void );

    void            SetDataWindow           (   int                         iFrameDecimationFactor,
                                                int                         iSampleDecimationFactor,
                                                unsigned long               ulDelayInSamples    = 0UL,
                                                unsigned long               ulTotalSamples      = 0UL,
                                                unsigned long               ulMaxPacketSize     = ulMaxEdgeTechDynamicDataSize_c );

    void            SetTxChannelGain        (   const int                   &riChannel,
                                                const int                   &riTxGain,
                                                const bool                  &rbUpdateConfig );

    void            SetHardTrigger          (   const   SonarMessageCouplingParametersType  &rsCouplingParameters );

    void            SetSoftTrigger          (   const   long                &rlDelayInMicroseconds );

    bool            IsValid                 (   const SidescanHeaderType    *psData );

    bool            IsValid                 (   const SegyDataType          *psData );

    bool            IsSSS                   (   void ) const;

    bool            IsSBP                   (   void ) const;

    bool            HandleSubbottomChannel  (   const unsigned long         &rulTimeStamp,
                                                const SegyDataType          *psData );

    bool            HandleSidescanChannel   (   const unsigned long         &rulTimeStamp,
                                                const SidescanHeaderType    *psData );

    bool            FormatEdgeTech7kSSSRecord(  const unsigned long         &rulPingNumber );

    bool            FormatEdgeTech7kSBPRecord(  const unsigned long         &rulTimeStamp,
                                                const SegyDataType          *psData );

    bool            Queue7kDataRecord       (   void );

    bool            Queue7kStatusRecord     (   BYTE                        *pbyRecord,
                                                const unsigned long         &rulBytes );

    bool            NotifyHostOfReply       (   void );

    bool            Reply                   (   const EREPLYTYPE            &reReplyType );

    void            HandleUpdatedStatus     (   const ESTATUSUPDATE         &reStatus,
                                                const unsigned long         &rulTimeStamp );

    void            ScaleChannelData        (   short                       *pnDest,
                                                const short                 *pnSource,
                                                const short                 &rnWeightFactor,
                                                const unsigned long         &rulSamples );

    void            SetSoftwareVersion      (   void );

    float           SoftwareVersion         (   void ) const;

    void            HandleSonarError        (   const CEdgeTechMessage      &rMessage,
                                                const unsigned long         &rulTimeStamp );

    template <typename tSonarChannel>
    bool            SendMessage             (   tSonarChannel               *pSonarChannel,
                                                CEdgeTechMessage            &rMessage );

    // Copy constructor and assignment operator not implemented.

                    CSubsystem              (   const CSubsystem            &rRhs );       // Not implemented.
    CSubsystem &    operator =              (   const CSubsystem            &rRhs );       // Not implemented.
};

#endif // !defined(AFX_SUBSYSTEM_H__7CFA7542_2EF7_47BA_B29B_F587CFF0D622__INCLUDED_)

