//
//  Copyright © 2003, 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:   Dispatcher.h
//
//  Project:    6046
//
//  Author(s):  W. Arcus
//
//  Purpose:    CDispatcher class definition.
//
//  Notes:      
//

#if !defined(AFX_DISPATCHER_H__B563E368_C0DF_4868_A341_6CF947A8D614__INCLUDED_)
#define AFX_DISPATCHER_H__B563E368_C0DF_4868_A341_6CF947A8D614__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "SubsystemIndex.h"
#include "7kSonarInterface.h"
#include "Parent.h"
#include "SystemInfo.h"

#include "..\..\..\Utils\NetUtils\Critical.h"

#pragma warning( push, 3 )                                                                                                          // Microsoft's STL is dirty so suppress necessary warnings.
#pragma warning( disable : 4018 4284 4146 )
#include <deque>
#include <list>
#pragma warning( default : 4018 4284 4146 )
#pragma warning( pop )

class CDispatcher
{
public:

    ///////////////
    // Definitions.

    enum EINTERFACETYPE
    {
        interfaceTypeLocal                                      = 0,                                                                // Local shared memory interface.
        interfaceTypeRemote                                                                                                         // Remote network connection.
    };

    ///////////////
    // Services.

                                CDispatcher                         (   void );                                                     // Default construction only allowed.
    virtual                    ~CDispatcher                         (   void );

    bool                        IsInitialized                       (   void ) const;                                               // Success indicator for construction of this object.

    bool                        CreateSubsystem                     (   PFN_SUBSYSTEMCALLBACK   pfnCallback,                        // Register a new subsystem and couple to a sonar interface -- new or existing.
                                                                        void                   *pvParam,
                                                                        const int              &riSensorIndex,
                                                                        const unsigned long    &rulDeviceId,
                                                                        const unsigned short   &runSystemEnumerator,
                                                                        const EINTERFACETYPE   &reInterfaceType     = interfaceTypeLocal,
                                                                        const unsigned long    &rulPortOut          = 7000UL,
                                                                        const unsigned long    &rulPortIn           = 7001UL,
                                                                        const char             *pszAddress          = "127.0.0.1" );

    bool                        DestroySubsystem                    (   const int              &riSensorIndex );                    // Remote the subsystem reference and destroy the sonar interface as necessary.

    bool                        Write7kRecord                       (   const int              &riSensorIndex,                      // Write a 7k formatted record to the specified subsystem (aka subsystem).
                                                                        const BYTE             *pby7kRecord,
                                                                        const unsigned long    &rulBytes );

    void                        GenericSensorData                   (   const bool            &rbEnable,                           // Subscribe or unsubscribe to generic sensor data.
                                                                        PFN_SUBSYSTEMCALLBACK  pfnCallback,
                                                                        void                  *pvParam );

    CSystemInfo::DeviceInfo_t   DeviceInfo                          (   const int              &riSensorIndex );                    // Get current system info (infered from inbound global 7k data records).

    bool                        HasRecordBeenReceived               (   const unsigned long    &rulRecordType,                      // Scans the received 7k message queue for the specified message id of the system to which the subsystem maps.
                                                                        const int              &riSensorIndex );

private:

    ///////////////
    // Definitions.

    class C7kSystem : private CSystemInfo, public CParent<CDispatcher>                                                              // System for a 7k sonar interface.
    {
    public:

        ///////////////
        // Services.

                                C7kSystem                           (   CDispatcher const *     pParent         = NULL );
        virtual                ~C7kSystem                           (   void );
                                C7kSystem                           (   const C7kSystem        &rRhs );
                                                                
        C7kSystem &             operator =                          (   const C7kSystem        &rRhs );

        bool                    operator <                          (   const C7kSystem        &rRhs )          const;              // Less than operator needed by std::list for sorting.

        bool                    operator ==                         (   const int              &riSystemIndex ) const;              // == operator used with std::find().

                                operator CSystemInfo *              (   void );                                                     // Conversion operator.

        void                    Add                                 (   void                   *pvInterface     = NULL );

        void                  * Remove                              (   void );

        void                    SystemIndex                         (   const                  &riSystemIndex );

        void                    InterfaceTypeInfo                   (   const int              &riType,
                                                                        const unsigned long    &rulPortOut,
                                                                        const unsigned long    &rulPortIn,
                                                                        const char             *pszAddress );
        // Read-only services.

        void                  * Interface                           (   void ) const;

        int                     Type                                (   void ) const;

        int                     ReferenceCount                      (   void ) const;

        int                     SystemIndex                         (   void ) const;

        bool                    HasRecordBeenReceived               (   const unsigned long    &rulRecordType );

    private:

        ///////////////
        // Definitions.

        typedef std::deque<unsigned long>                           ReceivedMessageQueue_t;
        typedef std::vector<unsigned long>                          RecordIgnoreList_t;                                             // STL vector containing known 7k record types to ignore.

        ///////////////
        // Attributes.

        const unsigned int      m_uiMaxReceiveQueueLength;

        int                     m_iSystemIndex;                                                                                     // Interface descriptor index.
        int                     m_iReferenceCount;                                                                                  // Number of subsystems mapped to this interface; determines interface life time.

        int                     m_iType;                                                                                            // Local ( = 0) or remote (=1) interface.

        unsigned long           m_ulPortOut;                                                                                        // TCP port for output from sonar if remote.
        unsigned long           m_ulPortIn;                                                                                         // TCP port for input  to   sonar if remote.
        char                    m_szAddress [ 16 ];                                                                                 // TCP host address if remote.

        ReceivedMessageQueue_t  m_ReceivedMessageQueue;                                                                             // Queue of 7k messages received; a constant maximum length is maintained.
        RecordIgnoreList_t      m_RecordIgnoreList;

        void                   *m_pvSonarInterface;                                                                                 // Pointer to the sonar interface itself.

        ///////////////
        // Services.

        static void             DataAvailable                       (   const void             *pvParam,
                                                                        const BYTE             *pby7kRecord,
                                                                        const unsigned long    &rulBytes,
                                                                        const unsigned long    &rulTimeStamp );

        bool                    HandleInterfaceData                 (   const BYTE             *pby7kRecord,
                                                                        const unsigned long    &rulBytes,
                                                                        const unsigned long    &rulTimeStamp );

        bool                    UpdateSystemStateAndDispatch        (   const BYTE             *pby7kRecord,
                                                                        const unsigned long    &rulBytes,
                                                                        const unsigned long    &rulTimeStamp );

        bool                    RegisterCallback                    (   PFN_SUBSYSTEMCALLBACK   pfnCallback,
                                                                        void                   *pvParam );

        bool                    DeregisterCallback                  (   void );

        void                    DecodeConfigrationSettings          (   const BYTE             *pby7kRecord );

        void                    AddRecordTypeToQueue                (   const unsigned long    &rulRecordType );

        bool                    IsIgnoreRecord                      (   const unsigned long    &rulRecordType );

    };

    class CGenericSensorDataDispatcher                                                                                          // Internal helper to encapsulate sensor non-specific data record dispatch.
    {
    private:

        bool                    m_bEnabled;
        PFN_SUBSYSTEMCALLBACK   m_pfnCallback;
        void                   *m_pvParam;

    public:

                                CGenericSensorDataDispatcher        (   void );

        virtual                ~CGenericSensorDataDispatcher        (   void );

        void                    Enable                              (   const bool             &rbEnable,
                                                                        PFN_SUBSYSTEMCALLBACK   pfnCallback,
                                                                        void                   *pvParam );

        bool                    IsEnabled                           (   void )                                  const;

        bool                    operator ()                         (   const BYTE             *pby7kRecord,
                                                                        const unsigned long    &rulBytes,
                                                                        const unsigned long    &rulTimeStamp )  const;
    };

    ///////////////
    // Definitions.

    friend class C7kSystem;                                                                                                     // Grant C7kSystem access to CDispatcher's private members.

    typedef std::list<CSubsystemIndex>                              SubsystemList_t;                                                // STL link-list for the subsystem (aka sensor) descriptions...
    typedef SubsystemList_t::iterator                               SubsystemListIterator_t;                                        // and its iterator.

    typedef std::list<C7kSystem>                                    SystemList_t;                                                   // STL link-list for the sonar interface descriptions...
    typedef SystemList_t::iterator                                  SystemListIterator_t;                                           // and its iterator.

    
    ///////////////
    // Attributes.

    bool                                                            m_bIntialized;                                                  // Construction success or failure flag.

    CCritical                                                       m_SubsystemListGuard;                                           // Critical section object to protect the m_Subsystems linked list (thread safe access).
    SubsystemList_t                                                 m_Subsystems;                                                   // Linked list of subsystem index info; contains the sonar interface map key.

    CCritical                                                       m_SystemListGuard;                                              // Critical section object to protect the m_Systems linked list (thread safe access).
    SystemList_t                                                    m_Systems;                                                      // Linked list describing the sonar interfaces to which the subsystems map. Note: multiple
                                                                                                                                    // subsystems may map to a single sonar interface.

    CGenericSensorDataDispatcher                                    m_GenericSensorDataDispatcher;                                  // Generic sensor data dispatching object.

    ///////////////
    // Services.

    bool                    IsRegistered                            (   const int                      &riSensorIndex,
                                                                        SubsystemListIterator_t        &rpSubsystem );

    CSubsystemIndex *       SubsystemFrom7kIds                      (   const unsigned long            &rulDeviceId,
                                                                        const unsigned short           &runSystemEnumerator );

    SubsystemListIterator_t SubsystemIteratorFromSensorIndex        (   const int                      &riSensorIndex );

    void                    SortSubsystemList                       (   void );
    void                    SortInterfaceList                       (   void );

    void                    DestroyAll                              (   void );

    int                     SystemIndexFromSensorIndex              (   const int                      &riSensorIndex );

    C7kSonarInterface *     SonarInterface                          (   const int                      &riSystemIndex );

    bool                    IsNewInterface                          (   const CSubsystemIndex          &rSubsystemIndex,
                                                                        const EINTERFACETYPE           &reInterfaceType );

    bool                    NewSystem                               (   C7kSystem                      &rSystem,
                                                                        const EINTERFACETYPE           &reInterfaceType,
                                                                        const unsigned long            &rulPortOut,
                                                                        const unsigned long            &rulPortIn,
                                                                        const char                     *pszAddress );

    bool                    InterfaceFromSubsystemInfo              (   SystemListIterator_t           &rpInterface,
                                                                        const CSubsystemIndex          &rSubsystemIndex,
                                                                        const EINTERFACETYPE           &reInterfaceType );

    bool                    DispatchToSubsystem                     (   const BYTE                     *pby7kRecord,
                                                                        const unsigned long            &rulBytes,
                                                                        const unsigned long            &rulTimeStamp,
                                                                        const bool                     &bDispatchToAllSubsystems );

    void                    HandleNonSpecificRecord                 (   const BYTE                     *pby7kRecord,
                                                                        const unsigned long            &rulBytes,
                                                                        const unsigned long            &rulTimeStamp );

    static void             DataAvailableCallback                   (   const void                     *pvParam,
                                                                        const BYTE                     *pby7kRecord,
                                                                        const unsigned long            &rulBytes,
                                                                        const unsigned long            &rulTimeStamp );

    static bool             IsRecordDeviceIndependent               (   const BYTE                     *pby7kRecord,
                                                                        const unsigned long            &rulBytes     );

    static bool             IsAckNakRecord                          (   const unsigned long            &rulRecordType );

    // Standard services not implemented by this class.

                            CDispatcher                             (   const CDispatcher              &rRhs );                     // Not implemented thus private.
    CDispatcher &           operator =                              (   const CDispatcher              &rRhs );                     // Not implemented thus private.
                                                                    
};

#endif // !defined(AFX_DISPATCHER_H__B563E368_C0DF_4868_A341_6CF947A8D614__INCLUDED_)

