#include <limits.h>
#include <crtdbg.h>
#include "SIStoragePropertyInternal.h"
#include "GroupPropertyInternal.h"
#include "Log.h"
#include "NdtsError.h"

namespace NDTS
{
	namespace SCO
	{
	SCO_API SIStoragePropertyInternal::SIStoragePropertyInternal(char *pShortName, char *pLongName, int flags, SI::BaseUnit baseUnit, SI::Prefix prefix, double defaultValue, double min, double max): 
												SIPropertyInternal(pShortName, pLongName, flags, baseUnit, prefix)
	{
		// We store everything internally in the SI base unit 
		// The parent SIPropertyInternal class takes care of the base unit to scaled unit conversion
		// However, our constructor is called with scaled units so we need to convert these scaled units
		// before storing them internally
		if (!pSIUnitInternal->getIsInverse())
		{
			staticMin = getSIUnit()->prefixToBase(min);
			staticMax = getSIUnit()->prefixToBase(max);
		}
		else
		{   // Min and max are specified in Mhz but the base unit is seconds so need to swap 
			staticMin = getSIUnit()->prefixToBase(max);
			staticMax = getSIUnit()->prefixToBase(min);
		}

		value = getSIUnit()->prefixToBase(defaultValue);
	}

	SCO_API SIStoragePropertyInternal::~SIStoragePropertyInternal(void)
	{
	}

	double SIStoragePropertyInternal::getSIValue()
	{
		return value;
	}

	void SIStoragePropertyInternal::setSIValue(double value)
	{
		if (value == this->value)
			return;
		// Always apply the change immediately with a StorageProperty, even when in a group.
		// This means that the value will be correct as soon as we end the group.
		// The SDK is never called on a setSIValue so it doesn't matter that we are setting a value during a groupChane.
		double clampedValue  = value;

		if (value < staticMin)
			clampedValue = staticMin;
		if (value > staticMax)
			clampedValue = staticMax;

		this->value = clampedValue;

		// Send the new value to our shadowing properties

		if (value != clampedValue)
		{
			// We only generate a value change event for us if the value has been clamped, not if succesfully applied.
			createChangeItem(CTValue);
			pLog->addError(SCO_PropertyValueOutOfRange, NDTS_LLDebug);
			pLog->addMessageToLog(NDTS_LLInfo, "%s value %f was clamped to %f",	pShortName,	value, clampedValue);
		}
		else
		{
			// Always generate a change event for our shadowed properties
			createChangeItemForShadowingProperties(CTValue);
		}
	}

	double SIStoragePropertyInternal::getSIMin()
	{
		return staticMin;

	}
	double SIStoragePropertyInternal::getSIMax()
	{
		return staticMax;
	}
}}