//
//  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:   ClientConnections.h
//
//  Project:    6046.
//
//  Author(s):  W. Arcus
//
//  Purpose:    
//
//  Notes:
//

#if !defined(AFX_CLIENTCONNECTIONS_H__058A96E0_3B8E_4C8E_911E_84672A2BC374__INCLUDED_)
#define AFX_CLIENTCONNECTIONS_H__058A96E0_3B8E_4C8E_911E_84672A2BC374__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "SocketServer.h"
#include "Parent.h"

#include "..\..\..\Utils\NetUtils\Critical.h"
#include "..\..\..\Utils\NetUtils\DataCallback.h"

class CConnectedClient
{
private:

    ///////////////
    // Attributes.

    const int   m_iInvalidIndex;
    int         m_iIndex;

public:

    ///////////////
    // Services.

    CConnectedClient( const int &riIndex = -1 ) : m_iInvalidIndex( -1 )
    {
        m_iIndex = riIndex;
    }

    CConnectedClient( const CConnectedClient &rRhs ) : m_iInvalidIndex( -1 )
    {
        m_iIndex = rRhs.m_iIndex;
    }

    virtual ~CConnectedClient( void )
    {
        m_iIndex = m_iInvalidIndex;
    }

    CConnectedClient & operator = ( const CConnectedClient &rRhs )
    {
        if ( this != &rRhs )
        {
            m_iIndex = rRhs.m_iIndex;
        }

        return *this;
    }

    bool operator == ( const int &riIndex ) const
    {
        return ( m_iIndex == riIndex );
    }

    bool operator < ( const CConnectedClient &rRhs ) const
    {
        return ( m_iIndex < rRhs.m_iIndex );
    }

    int SocketIndex( void ) const
    {
        return m_iIndex;
    }
};

class CClientConnections
{
public:

	                            CClientConnections  (   const unsigned long            &rulMaxMessageLength,
                                                        const unsigned int             &ruiListenPort,
                                                        PFN_DATACALLBACK                pfnCallback,
                                                        void *                          pvCallbackParam );

    virtual                    ~CClientConnections  (   void );

    bool                        IsInitialized       (   void ) const;

    bool                        Send                (   const int                       &riSocketIndex,
                                                        const BYTE                      *pbyRecord,
                                                        const unsigned long             &rulBytes );

    bool                        SendToAllClients    (   const BYTE                      *pbyData,
                                                        const unsigned long             &rulSize );

    bool                        Disconnect          (   const int                       &riSocketIndex );

private:

    ///////////////
    // Definitions.

    class CClientWatchThread : public virtual CBaseThread, public virtual CParent<CClientConnections>
    {
    public:

        enum ETHREADMESSAGES                                                    // Recognised thread messages.
        {
            messageDisconnect   =   threadMessageTerminate + 1                  // 
        };

                                CClientWatchThread  (   void );
        virtual                ~CClientWatchThread  (   void );

    protected:

        BOOL                    ProcessMessage      (   MSG                             *psMsg );

    };

    friend CClientWatchThread;                                                                              // Grant CClientWatchThread permission to access internals of its parent.

    typedef std::list<CConnectedClient>     ConnectedClientList_t;
    typedef ConnectedClientList_t::iterator ConnectedClientListIterator_t;

    ///////////////
    // Attributes.

    const unsigned long         m_ulMaxMessageLength;
    const unsigned int          m_uiListenPort;

    bool                        m_bInitialized;

    CClientWatchThread          m_WatchThread;
    CSocketServer              *m_pSocketServer;
    ConnectedClientList_t       m_ClientList;
    mutable CCritical           m_ClientAccessGuard;

    PFN_DATACALLBACK            m_pfnDataCallback;
    void *                      m_pvCallbackParam;

    ///////////////
    // Services.

    bool                        Dispatch                (   const BYTE                     *pbyData,
                                                            const unsigned long            &rulNumBytes,
                                                            const unsigned long            &rulTimeStamp,
                                                            const int                      &riSocketIndex );

    bool                        Connect                 (   const int                      &riSocketIndex );

    bool                        PostDisconnect          (   const int                      &riSocketIndex );

    bool                        ClientFromSocketIndex   (   const int                      &riSocketIndex,
                                                            ConnectedClientListIterator_t  &rpClientItem );

    static void             SocketRxHandler             (   BYTE                           *pbyData,
                                                            PVOID                           lpvParam,
                                                            ULONG                           ulNumBytes,
                                                            INT                             iSocketIndex,
                                                            ULONG                           ulTimeStamp,
                                                            INT                             iReasonForCallback );

    // Following services are not implemented.

	                    CClientConnections          (   void );                                             // Not implemented thus private.
                        CClientConnections          (   const CClientConnections       &rRhs );             // Not implemented thus private.
    CClientConnections & operator =                 (   const CClientConnections       &rRhs );             // Not implemented thus private.

};

#endif // !defined(AFX_CLIENTCONNECTIONS_H__058A96E0_3B8E_4C8E_911E_84672A2BC374__INCLUDED_)
