class TransferValues extends Managed
{
	const int TYPE_HEALTH 	= 1;
	const int TYPE_BLOOD 	= 2;
	
	const float VALUE_CHECK_INTERVAL	 	= 5;
	const float SENSITIVTY_PERCENTAGE 		= 1;//how much the value needs to change up/down from previous update to trigger a new update(in percent)

	const int BLOOD_THRESHOLD_LOW = 3000;
	PlayerBase m_Player;
	float m_TimeSinceLastTick = VALUE_CHECK_INTERVAL + 1;
	
	float m_LastHealthUpdate;
	float m_LastBloodUpdate;
	
	//float m_CumulatedHealthDiff;
	//float m_CumulatedBloodDiff;

	float m_HealthMaxValue;
	float m_BloodMaxValue;
	
	float m_BloodClient;
	float m_HealthClient;
	
	protected bool m_InitialSyncSent;
	
	void TransferValues(PlayerBase player)
	{
		m_Player = player;
		m_InitialSyncSent = false;
		Init();
	}
	
	void Init()
	{
		m_LastHealthUpdate 	= 0;
		m_LastBloodUpdate 	= 0;
		m_HealthMaxValue 	= m_Player.GetMaxHealth("", "Health");
		m_BloodMaxValue 	= m_Player.GetMaxHealth("", "Blood");
		m_BloodClient 		= 0;
		m_HealthClient 		= 0;
	}
	
	void OnScheduledTick(float deltatime)
	{
		#ifdef DIAG_DEVELOPER
		#ifndef SERVER
		ShowDebugValues(DiagMenu.GetBool(DiagMenuIDs.TRANSFER_VALUES_SHOW));
		#endif
		#endif
		
		if ( GetGame().IsClient() ) return;
		
		m_TimeSinceLastTick += deltatime;
		
		if (!m_InitialSyncSent)
		{
			SendInitValues();
		}
		else if ( m_TimeSinceLastTick > VALUE_CHECK_INTERVAL )
		{
			/*
			Print(m_TimeSinceLastTick.ToString());
			Print(VALUE_CHECK_INTERVAL.ToString());
			Print("--------------");
			*/
			m_TimeSinceLastTick = 0;
			CheckValues();
			
			// send sync junctures if necessary
			// TODO: !!!! event is sent too often, please fix it
			/*
			float damage = 1 - m_Player.GetHealth("", "") / 100;
			DayZPlayerSyncJunctures.SendInjury(m_Player, true, damage);
			*/
		}
	}
	
	void CheckValues()
	{
		CheckHealth();
		CheckBlood();
	}
	
	float GetBlood()
	{
		return m_BloodClient;
		
	}
	
	float GetHealth()
	{
		return m_HealthClient;
	}
	
	void CheckHealth()
	{
		float health_current = m_Player.GetHealth("","Health");
		float health_normalized = health_current / m_HealthMaxValue;
		float difference_normalized = health_normalized - m_LastHealthUpdate;
		float diff_abs = Math.AbsFloat(difference_normalized);
		
		if ( diff_abs > ( SENSITIVTY_PERCENTAGE / 100 ) )
		{
			SendValue(TYPE_HEALTH, health_normalized);
			m_LastHealthUpdate = health_normalized;
		}
	}
	
	void CheckBlood()
	{
		float blood_current = m_Player.GetHealth("","Blood");
		//float blood_normalized = blood_current / m_BloodMaxValue;
		float blood_normalized = Math.InverseLerp(BLOOD_THRESHOLD_LOW, m_BloodMaxValue, blood_current);
		blood_normalized = Math.Clamp(blood_normalized,0,1);
		float difference_normalized = blood_normalized - m_LastBloodUpdate;
		float diff_abs = Math.AbsFloat(difference_normalized);
		
		if ( diff_abs > ( SENSITIVTY_PERCENTAGE /100 ) )
		{
			SendValue(TYPE_BLOOD, blood_normalized);
			m_LastBloodUpdate = blood_normalized;
		}
	}
	
	//! Sends values on object creation
	void SendInitValues()
	{
		m_InitialSyncSent = true;
		
		//HP
		float health_current = m_Player.GetHealth("","Health");
		float health_normalized = health_current / m_HealthMaxValue;
		SendValue(TYPE_HEALTH, health_normalized);
		m_LastHealthUpdate = health_normalized;
		
		//Blood
		float blood_current = m_Player.GetHealth("","Blood");
		float blood_normalized = Math.InverseLerp(BLOOD_THRESHOLD_LOW, m_BloodMaxValue, blood_current);
		blood_normalized = Math.Clamp(blood_normalized,0,1);
		SendValue(TYPE_BLOOD, blood_normalized);
		m_LastBloodUpdate = blood_normalized;
	}
	
	void SendValue(int value_type, float value)
	{
		CachedObjectsParams.PARAM2_INT_FLOAT.param1 = value_type;
		CachedObjectsParams.PARAM2_INT_FLOAT.param2 = value;
		
		GetGame().RPCSingleParam(m_Player, ERPCs.RPC_DAMAGE_VALUE_SYNC, CachedObjectsParams.PARAM2_INT_FLOAT, true, m_Player.GetIdentity());
	}

	void ReceiveValue(int value_type, float value)
	{
		if ( value_type == TYPE_HEALTH )
		{
			m_HealthClient = value;
		}
		else if ( value_type == TYPE_BLOOD )
		{
			m_BloodClient = value;
		}
	}

	void OnRPC(ParamsReadContext ctx)
	{
		ctx.Read(CachedObjectsParams.PARAM2_INT_FLOAT);
		
		int value_type 	= CachedObjectsParams.PARAM2_INT_FLOAT.param1;
		float value 	= CachedObjectsParams.PARAM2_INT_FLOAT.param2;
		
		ReceiveValue(value_type, value);
	}
	
	void ShowDebugValues(bool show)
	{		
		#ifdef DIAG_DEVELOPER
		if ( show )
		{		
			DbgUI.BeginCleanupScope();     
	        DbgUI.Begin("Values", 50, 50);
			
	        DbgUI.Text("Blood: " + m_BloodClient.ToString());
			DbgUI.Text("Health: " + m_HealthClient.ToString());

	        DbgUI.End();
	        DbgUI.EndCleanupScope();
		}
		else
		{
			DbgUI.BeginCleanupScope();
			DbgUI.Begin("Values", 50, 50);
			DbgUI.End();
	        DbgUI.EndCleanupScope();   
		}
		#endif
	}	
}