//
//  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:   SensorStatus.cpp
//
//  Project:    6046
//
//  Author(s):  W. Arcus
//
//  Purpose:    
//
//  Notes:      
//

#include "StdAfx.h"
#include "SensorStatus.h"

#include "..\..\..\Utils\NetUtils\SystemTime.h"

//////////////////////////////////////////////////////////////////////
// CSensorStatus class implementation.

using std::string;

CSensorStatus::CSensorStatus                ( void )
              :m_ulDefaultNonResponsePeriod ( 2000UL )
{
    m_bHealthy            = true;
    m_ulNonResponsePeriod = m_ulDefaultNonResponsePeriod;
    m_ulTimeOfLastUpdate  = 0UL;

    m_MessageQueue.clear();
}

CSensorStatus::~CSensorStatus( void )
{
    m_bHealthy            = false;
    m_ulTimeOfLastUpdate  = 0UL;
    m_ulNonResponsePeriod = 0UL;

    m_MessageQueue.clear();
}

void CSensorStatus::SetTimeoutPeriod( const unsigned long &rulTimeoutInMilliseconds )
{
    __TRY
    {
        m_StateGuard.Enter();

        m_ulNonResponsePeriod = rulTimeoutInMilliseconds;
    }
    __FINALLY
    {
        m_StateGuard.Leave();
    }
    __ENDFINALLY
}

bool CSensorStatus::IsQueued( void ) const
{
    bool bMessageAvailable = false;

    __TRY
    {
        m_StateGuard.Enter();
        bMessageAvailable = ! m_MessageQueue.empty();
    }
    __FINALLY
    {
        m_StateGuard.Leave();
    }
    __ENDFINALLY

    return bMessageAvailable;
}

bool CSensorStatus::QueueMessage( const CSensorStatus::CMessageDescriptor &rMessageDescriptor )
{
    __TRY
    {
        m_StateGuard.Enter();
        m_MessageQueue.push_back( rMessageDescriptor );
    }
    __FINALLY
    {
        m_StateGuard.Leave();
    }
    __ENDFINALLY

    return true;
}

bool CSensorStatus::RetrieveNextMessage( CSensorStatus::CMessageDescriptor &rMessageDescriptor )
{
    bool bRetrieved = false;

    rMessageDescriptor.Clear();

    __TRY
    {
        m_StateGuard.Enter();

        if ( ! m_MessageQueue.empty() )
        {
            rMessageDescriptor = m_MessageQueue.front();
            m_MessageQueue.pop_front();
            bRetrieved = true;
        }
    }
    __FINALLY
    {
        m_StateGuard.Leave();
    }
    __ENDFINALLY

    return bRetrieved;
}

void CSensorStatus::Health( const bool &rbHealthy )
{
    __TRY
    {
        m_StateGuard.Enter();

        m_bHealthy = rbHealthy;

        if ( rbHealthy )
        {
            m_ulTimeOfLastUpdate = CSystemTime::GetTickCount();
        }
    }
    __FINALLY
    {
        m_StateGuard.Leave();
    }
    __ENDFINALLY
}

bool CSensorStatus::IsHealthy( void )
{
    bool bHealthy = true;

    __TRY
    {
        m_StateGuard.Enter();

        bHealthy = m_bHealthy;

        if ( ( CSystemTime::GetTickCount() - m_ulTimeOfLastUpdate ) > m_ulNonResponsePeriod )
        {
            bHealthy = false;
        }
    }
    __FINALLY
    {
        m_StateGuard.Leave();
    }
    __ENDFINALLY

    return bHealthy;
}

void CSensorStatus::Reset( void )
{
    __TRY
    {
        m_StateGuard.Enter();

        m_bHealthy           = true;
        m_ulTimeOfLastUpdate = CSystemTime::GetTickCount();
        m_MessageQueue.clear();
    }
    __FINALLY
    {
        m_StateGuard.Leave();
    }
    __ENDFINALLY
}

//////////////////////////////////////////////////////////////////////
// CSensorStatus class implementation.

CSensorStatus::CMessageDescriptor::CMessageDescriptor( void )
{
    m_iType                 = 0;
    m_iMode                 = 0;
    m_iId                   = 0;
    m_ulTimeStamp           = 0UL;
    m_sMessage              = "";

    m_bAckNak               = false;
    m_eAckNakType           = ackNakTypeUnspecified;
    m_iClientIndex          = -1;
    m_ulRemoteControlId     = 0UL;
}

CSensorStatus::CMessageDescriptor::~CMessageDescriptor( void )
{
    m_iType                 = 0;
    m_iMode                 = 0;
    m_iId                   = 0;
    m_ulTimeStamp           = 0UL;

    m_sMessage.erase();

    m_bAckNak               = false;
    m_eAckNakType           = ackNakTypeUnspecified;
    m_iClientIndex          = -1;
    m_ulRemoteControlId     = 0UL;
}

CSensorStatus::CMessageDescriptor::CMessageDescriptor( const CSensorStatus::CMessageDescriptor &rRhs )
{
    m_iType                 = rRhs.m_iType;
    m_iMode                 = rRhs.m_iMode;
    m_iId                   = rRhs.m_iId;

    m_ulTimeStamp           = rRhs.m_ulTimeStamp;
    m_sMessage              = rRhs.m_sMessage;

    m_bAckNak               = rRhs.m_bAckNak;
    m_eAckNakType           = rRhs.m_eAckNakType;
    m_iClientIndex          = rRhs.m_iClientIndex;
    m_ulRemoteControlId     = rRhs.m_ulRemoteControlId;
}

CSensorStatus::CMessageDescriptor & CSensorStatus::CMessageDescriptor::operator = ( const CSensorStatus::CMessageDescriptor &rRhs )
{
    if ( this != &rRhs )
    {
        m_iType             = rRhs.m_iType;
        m_iMode             = rRhs.m_iMode;
        m_iId               = rRhs.m_iId;
        m_ulTimeStamp       = rRhs.m_ulTimeStamp;
        m_sMessage          = rRhs.m_sMessage;

        m_bAckNak           = rRhs.m_bAckNak;
        m_eAckNakType       = rRhs.m_eAckNakType;
        m_iClientIndex      = rRhs.m_iClientIndex;
        m_ulRemoteControlId = rRhs.m_ulRemoteControlId;
    }

    return *this;
}

void CSensorStatus::CMessageDescriptor::Clear( void )
{
    m_iType                 = 0;
    m_iMode                 = 0;
    m_iId                   = 0;
    m_ulTimeStamp           = 0UL;
    m_sMessage.erase();

    m_bAckNak               = false;
    m_eAckNakType           = ackNakTypeUnspecified;
    m_iClientIndex          = -1;
    m_ulRemoteControlId     = 0UL;
}

void CSensorStatus::CMessageDescriptor::SetAckNak(  const EACKNAKTYPE   &reAckNakType,
                                                    const int           &riClientIndex,
                                                    const unsigned long &rulRemoteControlId )
{
    m_bAckNak           = true;
    m_eAckNakType       = reAckNakType;
    m_iClientIndex      = riClientIndex;
    m_ulRemoteControlId = rulRemoteControlId;
}

bool CSensorStatus::CMessageDescriptor::IsAckNak( void ) const
{
    return m_bAckNak;
}
