//----------------------------------------------------------------------------------
// <copyright file="SBDStatisticsEvent.cpp" company="LiquidRobotics">
//
// Copyright (c) 2014 Liquid Robotics, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// This software is associated with a release.  Liquid Robotics makes no
// representation that the design, interfaces or component distribution will
// remain unchanged in future releases.
//
// </copyright>
//
// <summary>
//   Implementation of the SBDStatisticsEvent class, which carries module statistics
//   values.
// </summary>
//
// <owner>Mike Cookson</owner>
//----------------------------------------------------------------------------------

#include "SBDStatisticsEvent.h"
#include "LqrSMACBooleanParser.h"
#include "LqrSMACIdl.h"
#include "nsextend.h"

using namespace std;
using namespace LiquidRobotics::SMACFramework;

namespace LiquidRobotics {
namespace EventLib {

#define EVENT_PREFIX "SBDStatisticsEvent_"

const SBDStatisticsEvent::PropertyNameType SBDStatisticsEvent::CommunicatingTag = EVENT_PREFIX "Communicating";
const SBDStatisticsEvent::PropertyNameType SBDStatisticsEvent::NetworkOKTag = EVENT_PREFIX "NetworkOK";
const SBDStatisticsEvent::PropertyNameType SBDStatisticsEvent::AccessOKTag = EVENT_PREFIX "AccessOK";
const SBDStatisticsEvent::PropertyNameType SBDStatisticsEvent::ModelTag = EVENT_PREFIX "Model";
const SBDStatisticsEvent::PropertyNameType SBDStatisticsEvent::SerialNumTag = EVENT_PREFIX "SerialNum";
const SBDStatisticsEvent::PropertyNameType SBDStatisticsEvent::SimNumTag = EVENT_PREFIX "SimNum";
const SBDStatisticsEvent::PropertyNameType SBDStatisticsEvent::NumSentTag = EVENT_PREFIX "NumSent";
const SBDStatisticsEvent::PropertyNameType SBDStatisticsEvent::NumReceivedTag = EVENT_PREFIX "NumReceived";
const SBDStatisticsEvent::PropertyNameType SBDStatisticsEvent::NumSessionsTag = EVENT_PREFIX "NumSessions";
const SBDStatisticsEvent::PropertyNameType SBDStatisticsEvent::NumSessionsSuccessfulTag = EVENT_PREFIX "NumSessionsOK";
const SBDStatisticsEvent::PropertyNameType SBDStatisticsEvent::ReliableTag = EVENT_PREFIX "Reliable";

SBDStatisticsEvent::SBDStatisticsEvent(IObjectBroker& _broker)
: Base(_broker)
{
}

SBDStatisticsEvent::SBDStatisticsEvent(const EventSettings& _eventSettings, IObjectBroker& _broker)
: Base(_eventSettings, _broker)
{
}

SBDStatisticsEvent::SBDStatisticsEvent(const EventName& _eventName, const EventType& _eventType, IObjectBroker& _broker)
: Base(_eventName, _eventType, _broker)
{
}

SBDStatisticsEvent::SBDStatisticsEvent(const EventName& _eventName, const EventType& _eventType, const IOR& _senderIOR, IObjectBroker& _broker)
: Base(_eventName, _eventType, _senderIOR, _broker)
{
}

SBDStatisticsEvent::SBDStatisticsEvent(const SBDStatisticsEvent& other)
: Base(other)
{
}

struct BooleanStreamer
{
    static bool Write(const IEventBase& eb, ostream& stm, const string& tag)
    {
        if (eb.ContainsProperty(tag))
        {
            stm << BooleanToString(eb.GetProperty(tag).GetBoolean());
            return true;
        }
        else
            return false;
    }
};

struct StringStreamer
{
    static bool Write(const IEventBase& eb, ostream& stm, const string& tag)
    {
        if (eb.ContainsProperty(tag))
        {
            string str = eb.GetProperty(tag).GetString();
            stm << "'" << str << "'";
            return true;
        }
        else
            return false;
    }
};

struct UnsignedStreamer
{
    static bool Write(const IEventBase& eb, ostream& stm, const string& tag)
    {
        if (eb.ContainsProperty(tag))
        {
            stm << eb.GetProperty(tag).GetUInt32();
            return true;
        }
        else
            return false;
    }
};

template<typename T>
void DoStream(const IEventBase& eb, ostream& stm, const string& tag, const string& desc)
{
    stm << " " << desc << "=";

    bool good;

    try { good = T::Write(eb, stm, tag); }
    catch(...) { good = false; }

    if (!good)
        stm << "???";
}


ostream& SBDStatisticsEvent::Describe(ostream& stm) const
{
	Base::Describe(stm);

    DoStream<BooleanStreamer>(*this, stm, CommunicatingTag, "communicating");
    DoStream<BooleanStreamer>(*this, stm, NetworkOKTag, "networkOK");
    DoStream<BooleanStreamer>(*this, stm, AccessOKTag, "accessOK");
    DoStream<StringStreamer>(*this, stm, ModelTag, "model");
    DoStream<StringStreamer>(*this, stm, SerialNumTag, "serialNum");
    DoStream<StringStreamer>(*this, stm, SimNumTag, "simNum");
    DoStream<UnsignedStreamer>(*this, stm, NumSentTag, "numSent");
    DoStream<UnsignedStreamer>(*this, stm, NumReceivedTag, "numReceived");
    DoStream<UnsignedStreamer>(*this, stm, NumSessionsTag, "numSessions");
    DoStream<UnsignedStreamer>(*this, stm, NumSessionsSuccessfulTag, "numSessionsOK");
    DoStream<BooleanStreamer>(*this, stm, ReliableTag, "reliable");

	return stm;
}

IEventBase::Ptr SBDStatisticsEvent::Duplicate() const
{
	IEventBase::Ptr result;
	result.reset(new SBDStatisticsEvent(*this));

	return result;
}


void SBDStatisticsEvent::Init(bool communicating, bool networkOK, bool accessOK, const string& model, const string& serialNum, const string& simNum, unsigned numSent, unsigned numReceived, unsigned numSessions, unsigned numSessionsSuccessful, bool reliable)
{
    { EventPropertyValue epv(broker); epv.SetBoolean(communicating); SetProperty(CommunicatingTag, epv); }
    { EventPropertyValue epv(broker); epv.SetBoolean(networkOK); SetProperty(NetworkOKTag, epv); }
    { EventPropertyValue epv(broker); epv.SetBoolean(accessOK); SetProperty(AccessOKTag, epv); }
    { EventPropertyValue epv(broker); epv.SetString(model); SetProperty(ModelTag, epv); }
    { EventPropertyValue epv(broker); epv.SetString(serialNum); SetProperty(SerialNumTag, epv); }
    { EventPropertyValue epv(broker); epv.SetString(simNum); SetProperty(SimNumTag, epv); }
    { EventPropertyValue epv(broker); epv.SetUInt32(numSent); SetProperty(NumSentTag, epv); }
    { EventPropertyValue epv(broker); epv.SetUInt32(numReceived); SetProperty(NumReceivedTag, epv); }
    { EventPropertyValue epv(broker); epv.SetUInt32(numSessions); SetProperty(NumSessionsTag, epv); }
    { EventPropertyValue epv(broker); epv.SetUInt32(numSessionsSuccessful); SetProperty(NumSessionsSuccessfulTag, epv); }
    { EventPropertyValue epv(broker); epv.SetBoolean(reliable); SetProperty(ReliableTag, epv); }
}

bool SBDStatisticsEvent::GetCommunicating() const
{
	const bool result = GetProperty(CommunicatingTag).GetBoolean();
	return result;
}

bool SBDStatisticsEvent::GetNetworkOK() const
{
	const bool result = GetProperty(NetworkOKTag).GetBoolean();
	return result;
}

bool SBDStatisticsEvent::GetAccessOK() const
{
	const bool result = GetProperty(AccessOKTag).GetBoolean();
	return result;
}

string SBDStatisticsEvent::GetModel() const
{
	const string result = GetProperty(ModelTag).GetString();
	return result;
}

string SBDStatisticsEvent::GetSerialNum() const
{
	const string result = GetProperty(SerialNumTag).GetString();
	return result;
}

string SBDStatisticsEvent::GetSimNum() const
{
	const string result = GetProperty(SimNumTag).GetString();
	return result;
}

unsigned SBDStatisticsEvent::GetNumSent() const
{
	const unsigned result = GetProperty(NumSentTag).GetUInt32();
	return result;
}

unsigned SBDStatisticsEvent::GetNumReceived() const
{
	const unsigned result = GetProperty(NumReceivedTag).GetUInt32();
	return result;
}

unsigned SBDStatisticsEvent::GetNumSessions() const
{
	const unsigned result = GetProperty(NumSessionsTag).GetUInt32();
	return result;
}

unsigned SBDStatisticsEvent::GetNumSessionsSuccessful() const
{
	const unsigned result = GetProperty(NumSessionsSuccessfulTag).GetUInt32();
	return result;
}

bool SBDStatisticsEvent::GetReliable() const
{
	const bool result = GetProperty(ReliableTag).GetBoolean();
	return result;
}

}
}
