//
//  Copyright (c) 2001, Reson, Inc. All Rights Reserved.
//
//  Filename:   ConnectedClient.cpp
//
//  Project:    6046.
//
//  Author(s):  W. Arcus
//
//  Purpose:    
//
//  Notes:      

#include "StdAfx.h"
#include "ConnectedClient.h"

#include <algorithm>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// CConnectedClient class implementation.

CConnectedClient::CConnectedClient( const int &riIndex )
                 :m_iInvalidIndex( -1 )
{
    m_iIndex       = riIndex;
    m_bVerboseMode = false;

    m_SubscriptionList.clear();
    m_AlarmSuppressionList.clear();
}

CConnectedClient::CConnectedClient( const CConnectedClient &rRhs )
                 :m_iInvalidIndex( -1 )
{
    m_iIndex       = rRhs.m_iIndex;
    m_bVerboseMode = rRhs.m_bVerboseMode;

    m_SubscriptionList.clear();

    if ( ! rRhs.m_SubscriptionList.empty() )
    {
        m_SubscriptionList = rRhs.m_SubscriptionList;
    }

    if ( ! rRhs.m_AlarmSuppressionList.empty() )
    {
        m_AlarmSuppressionList = rRhs.m_AlarmSuppressionList;
    }
}

CConnectedClient::~CConnectedClient( void )
{
    try
    {
        m_iIndex       = m_iInvalidIndex;
        m_bVerboseMode = false;

        m_SubscriptionList.clear();
        m_AlarmSuppressionList.clear();
    }
    catch ( ... )
    {
        TRACE( _T( "CConnectedClient::~CConnectedClient(), Unspecified exception caught.\n" ) );
    }
}

CConnectedClient & CConnectedClient::operator = ( const CConnectedClient &rRhs )
{
    m_iIndex       = rRhs.m_iIndex;
    m_bVerboseMode = rRhs.m_bVerboseMode;

    m_SubscriptionList.clear();

    if ( ! rRhs.m_SubscriptionList.empty() )
    {
        m_SubscriptionList = rRhs.m_SubscriptionList;
    }

    if ( ! rRhs.m_AlarmSuppressionList.empty() )
    {
        m_AlarmSuppressionList = rRhs.m_AlarmSuppressionList;
    }

    return *this;
}

bool CConnectedClient::operator == ( const int &riIndex ) const
{
    return ( m_iIndex == riIndex );
}

bool CConnectedClient::operator < ( const CConnectedClient &rRhs ) const
{
    return ( m_iIndex < rRhs.m_iIndex );
}

int CConnectedClient::SocketIndex( void ) const
{
    return m_iIndex;
}

bool CConnectedClient::Verbose( void ) const
{
    return m_bVerboseMode;
}

void CConnectedClient::Verbose( const bool &rbVerbose )
{
    m_bVerboseMode = rbVerbose;
}

bool CConnectedClient::Subscribe(   const   int             &riSensorIndex,
                                    const   unsigned long   &rulRecordType )
{
    // Determine whether this record/sensor pair are already being subscribed to. If not,
    // subscribe otherwise, do nothing.

    if ( ! IsSubscribedRecord( riSensorIndex, rulRecordType ) )
    {
        // Push the new subscription on our list.

        SUBSCRIPTION sSubscription( riSensorIndex, rulRecordType );
        m_SubscriptionList.push_back( sSubscription );

        // Keep the list sorted.

        m_SubscriptionList.sort();
    }

    return true;
}

bool CConnectedClient::Unsubscribe( const int           &riSensorIndex,
                                    const unsigned long &rulRecordType )
{
    if ( ! m_SubscriptionList.empty() )
    {
        SubscriptionListIterator_t pItem;

        SUBSCRIPTION sCompareItem( riSensorIndex, rulRecordType );

        for ( pItem = m_SubscriptionList.begin(); pItem != m_SubscriptionList.end(); pItem++ )
        {
            if ( *(pItem) == sCompareItem )
            {
                m_SubscriptionList.erase( pItem );
                break;
            }
        }
    }

    if ( ! m_SubscriptionList.empty() )
    {
        m_SubscriptionList.sort();
    }

    return true;
}

bool CConnectedClient::UnsubscribeAll( void )
{
    m_SubscriptionList.clear();

    return ( m_SubscriptionList.empty() );
}

bool CConnectedClient::IsSubscribedRecord(  const int           &riSensorIndex,
                                            const unsigned long &rulRecordType )
{
    bool bSubscribed = false;

    if ( ! m_SubscriptionList.empty() )
    {
        SUBSCRIPTION sCompareItem( riSensorIndex, rulRecordType );

        SubscriptionListIterator_t pItem;

        for ( pItem = m_SubscriptionList.begin(); pItem != m_SubscriptionList.end(); pItem++ )
        {
            if ( *(pItem) == sCompareItem )
            {
                bSubscribed = true;
                break;
            }
        }
    }

    return bSubscribed;
}

bool CConnectedClient::AlarmMode(   const EALARMID &reAlarmId,
                                    const int      &riAlarmAction )
{
    bool bSuccess = false;

    try
    {
        bool bSuppressAlarm = static_cast<bool>( riAlarmAction == 0 );

        if ( m_AlarmSuppressionList.empty() )
        {
            if ( bSuppressAlarm )
            {
                m_AlarmSuppressionList.push_back( static_cast<int>( reAlarmId ) );
            }
        }
        else
        {
            AlarmSuppressionListIterator_t pAlarm = std::find( m_AlarmSuppressionList.begin(), m_AlarmSuppressionList.end(), static_cast<int>( reAlarmId ) );

            if ( bSuppressAlarm )
            {
                if ( pAlarm == m_AlarmSuppressionList.end() )
                {
                    m_AlarmSuppressionList.push_back( static_cast<int>( reAlarmId ) );
                }
            }
            else if ( pAlarm != m_AlarmSuppressionList.end() )
            {
                m_AlarmSuppressionList.erase( pAlarm );
            }   
        }

        bSuccess = true;
    }
    catch ( ... )
    {
        bSuccess = false;
    }

    return bSuccess;
}

bool CConnectedClient::IsAlarmReportable( const EALARMID &reAlarmId ) const
{
    bool bReportable = true;

    if ( ! m_AlarmSuppressionList.empty() )
    {
        bReportable = ( std::find( m_AlarmSuppressionList.begin(), m_AlarmSuppressionList.end(), static_cast<int>( reAlarmId ) ) == m_AlarmSuppressionList.end() );
    }

    return bReportable;
}
