//--------------------------------------------------------------------------------
// <copyright file="TelemetryReportParameters.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 TelemetryReportParmaeters, a serializable entity class that
//   represents the settings for a type of telemetry report.
// </summary>
//
// <owner>Mike Cookson</owner>
//--------------------------------------------------------------------------------

#include "TelemetryReportParameters.h"
#include "nsextend.h"

using namespace std;
using namespace LiquidRobotics::SMACFramework;
using namespace LiquidRobotics::SMACFramework::XmlDOM;

namespace LiquidRobotics {
namespace PayloadInterface {

TelemetryReportParameters::TelemetryReportParameters()
: maxSamples(1)
, maxRetainTime((time_t) -1)
, targetAddress(0)
{
}

TelemetryReportParameters::TelemetryReportParameters(uint16_t _maxSamples, time_t _maxRetainTime, BoardAddress _targetAddress)
: maxSamples(_maxSamples)
, maxRetainTime(_maxRetainTime)
, targetAddress(_targetAddress)
{
}

TelemetryReportParameters::TelemetryReportParameters(uint16_t _maxSamples, time_t _maxRetainTime, BoardAddress _targetAddress, const TelemetryFieldList& _reportHeaderFormat, const TelemetryFieldList& _sampleHeaderFormat)
: maxSamples(_maxSamples)
, maxRetainTime(_maxRetainTime)
, reportHeaderFormat(_reportHeaderFormat)
, sampleHeaderFormat(_sampleHeaderFormat)
, targetAddress(_targetAddress)
{
}

int TelemetryReportParameters::Compare(const TelemetryReportParameters& item1, const TelemetryReportParameters& item2)
{
	int result;

	if (item1.maxSamples < item2.maxSamples)
		result = -1;
	else if (item1.maxSamples > item2.maxSamples)
		result = 1;
	else if (item1.maxRetainTime < item2.maxRetainTime)
		result = -1;
	else if (item1.maxRetainTime > item2.maxRetainTime)
		result = 1;
	else if (item1.targetAddress < item2.targetAddress)
		result = -1;
	else if (item1.targetAddress > item2.targetAddress)
		result = 1;
	else if (item1.reportHeaderFormat < item2.reportHeaderFormat)
		result = -1;
	else if (item1.reportHeaderFormat > item2.reportHeaderFormat)
		result = 1;
	else if (item1.sampleHeaderFormat < item2.sampleHeaderFormat)
		result = -1;
	else if (item1.sampleHeaderFormat > item2.sampleHeaderFormat)
		result = 1;
	else
		result = 0;

	return result;
}

bool TelemetryReportParameters::operator==(const TelemetryReportParameters& other) const
{
	return Compare(*this, other) == 0;
}

bool TelemetryReportParameters::operator<(const TelemetryReportParameters& other) const
{
	return Compare(*this, other) < 0;
}

bool TelemetryReportParameters::operator>(const TelemetryReportParameters& other) const
{
	return Compare(*this, other) > 0;
}

uint16_t TelemetryReportParameters::GetMaxSamples() const
{
	return maxSamples;
}

time_t TelemetryReportParameters::GetMaxRetainTime() const
{
	return maxRetainTime;
}

const TelemetryFieldList& TelemetryReportParameters::GetReportHeaderFormat() const
{
	return reportHeaderFormat;
}

const TelemetryFieldList& TelemetryReportParameters::GetSampleHeaderFormat() const
{
	return sampleHeaderFormat;
}

TelemetryReportParameters::BoardAddress TelemetryReportParameters::GetTargetAddress() const
{
	return targetAddress;
}

void TelemetryReportParameters::SetMaxSamples(uint16_t newValue)
{
	maxSamples = newValue;
}

void TelemetryReportParameters::SetMaxRetainTime(time_t newValue)
{
	maxRetainTime = newValue;
}

void TelemetryReportParameters::SetReportHeaderFormat(const TelemetryFieldList& newValue)
{
	reportHeaderFormat = newValue;
}

void TelemetryReportParameters::SetSampleHeaderFormat(const TelemetryFieldList& newValue)
{
	sampleHeaderFormat = newValue;
}

void TelemetryReportParameters::SetTargetAddress(BoardAddress newValue)
{
	targetAddress = newValue;
}

void TelemetryReportParameters::Load(XmlNode& node, const XmlNVPBase& nvp)
{
	LoadFromNode(node, XmlNVPBase("", "maxSamples"), maxSamples);

	if (GetAttribute("maxRetainTime", node, false))
	{
		int32_t maxRetainTime2;

		LoadFromNode(node, XmlNVPBase("", "maxRetainTime"), maxRetainTime2);

		if (maxRetainTime2 < -1)
			throw runtime_error("TelemetryReportParameters maxRetainTime cannot be less than -1");

		maxRetainTime = (time_t) maxRetainTime2;
	}
	else
		maxRetainTime = (time_t) -1;

	if (GetAttribute("targetAddress", node, false))
		LoadFromNode(node, XmlNVPBase("", "targetAddress", XmlNVPBase::HEX), targetAddress);
	else
		targetAddress = 0;

	node >> XmlNVP<TelemetryFieldList>("reportHeaderFormat", reportHeaderFormat);
	node >> XmlNVP<TelemetryFieldList>("sampleHeaderFormat", sampleHeaderFormat);
}

void TelemetryReportParameters::Save(XmlNode& node, const XmlNVPBase& nvp) const
{
	SaveToNode(node, XmlNVPBase("", "maxSamples"), maxSamples);

	if (maxRetainTime != (time_t) -1)
	{
		const int32_t maxRetainTime2 = (int32_t) maxRetainTime;

		SaveToNode(node, XmlNVPBase("", "maxRetainTime"), maxRetainTime2);
	}

	SaveToNode(node, XmlNVPBase("", "targetAddress", XmlNVPBase::HEX), targetAddress);

	node << XmlNVP<TelemetryFieldList>("reportHeaderFormat", reportHeaderFormat);
	node << XmlNVP<TelemetryFieldList>("sampleHeaderFormat", sampleHeaderFormat);
}

ostream& operator<<(ostream& stm, const TelemetryReportParameters& prm)
{
	stm << "maxSamples=" << prm.GetMaxSamples()
	    << " maxRetainTime=" << prm.GetMaxRetainTime()
	    << " targetAddress=0x" << utos(prm.GetTargetAddress(), 16, 4)
	    << " reportHeaderFormat={ " << prm.GetReportHeaderFormat() << " }"
	    << " sampleHeaderFormat={ " << prm.GetSampleHeaderFormat() << " }";

	return stm;
}

}
}
