
class BleedingIndicatorDropData
{
	protected ImageWidget 	m_Widget;
	protected int 			m_Severity;
	protected float 		m_TimeTotal;
	protected float 		m_ProgressBreakpointTime;
	protected float 		m_ProgressFadingDuration; //remaining duration AFTER breakpoint
	protected float 		m_ProgressBreakpoint;
	protected float 		m_Duration;
	protected float 		m_SpeedCoef;
	protected int 			m_ScatterPx;
	protected float 		m_SlideDistance;
	
	protected float 		m_ColorAlphaStart;
	protected float 		m_ColorAlphaEnd;
	protected float 		m_ColorAlphaCurrent;
	
	protected float 		m_ImageBaseSizeX;
	protected float 		m_ImageBaseSizeY;
	protected float 		m_ImageStartingSizeX; //adjusted by percentage
	protected float 		m_ImageStartingSizeY; //adjusted by percentage
	protected float 		m_ImageEndSizeX; //adjusted by percentage
	protected float 		m_ImageEndSizeY; //adjusted by percentage
	protected float 		m_ImageMaxSizeX;
	protected float 		m_ImageMaxSizeY;
	protected float 		m_ImageBaseRotation;
	protected bool 			m_IsRunning;
	protected vector 		m_BasePosition;
	protected int 			m_ScreenSizeX;
	protected int 			m_ScreenSizeY;
	protected float 		m_PosX, m_PosY;
	protected float 		m_StartSizeCoef;
	protected float 		m_EndSizeCoef;
	protected float 		m_RandomSizeMin;
	protected float 		m_RandomSizeMax;
	
	//Written with relative positioning in mind
	void BleedingIndicatorDropData(ImageWidget image, int severity)
	{
		m_Widget = image;
		m_Severity = severity;
		m_TimeTotal = 0;
		m_IsRunning = false;
		
#ifdef DIAG_DEVELOPER
		if (DbgBleedingIndicationStaticInfo.m_DbgUseOverrideValues)
		{
			m_Duration = DbgBleedingIndicationStaticInfo.m_DbgDropDurationBase;
			m_ProgressBreakpointTime = m_Duration * DbgBleedingIndicationStaticInfo.m_DbgDropProgressTreshold;
			m_ProgressBreakpoint = DbgBleedingIndicationStaticInfo.m_DbgDropProgressTreshold;
			m_StartSizeCoef = DbgBleedingIndicationStaticInfo.m_DbgDropStartSize;
			m_EndSizeCoef = DbgBleedingIndicationStaticInfo.m_DbgDropEndSize;
			m_RandomSizeMin = DbgBleedingIndicationStaticInfo.m_DbgDropSizeVariationMin;
			m_RandomSizeMax = DbgBleedingIndicationStaticInfo.m_DbgDropSizeVariationMax;
			m_ScatterPx = DbgBleedingIndicationStaticInfo.m_DbgDropScatter;
			m_SlideDistance = DbgBleedingIndicationStaticInfo.m_DbgDropSlideDistance;
		}
		else
#endif
		{
			switch (m_Severity)
			{
				case BleedingIndicationConstants.INDICATOR_SEVERITY_LOW:
				{
					m_Duration = BleedingIndicationConstants.DROP_DURATION_LOW;
					m_StartSizeCoef = BleedingIndicationConstants.DROP_SIZE_START_LOW;
					m_EndSizeCoef = BleedingIndicationConstants.DROP_SIZE_END_LOW;
					m_RandomSizeMin = BleedingIndicationConstants.DROP_SIZE_VARIATION_MIN_LOW;
					m_RandomSizeMax = BleedingIndicationConstants.DROP_SIZE_VARIATION_MAX_LOW;
					m_ScatterPx = BleedingIndicationConstants.DROP_SCATTER_LOW;
					m_SlideDistance = BleedingIndicationConstants.DROP_SLIDE_DISTANCE_LOW;
					break;
				}
				case BleedingIndicationConstants.INDICATOR_SEVERITY_MEDIUM:
				{
					m_Duration = BleedingIndicationConstants.DROP_DURATION_MEDIUM;
					m_StartSizeCoef = BleedingIndicationConstants.DROP_SIZE_START_MEDIUM;
					m_EndSizeCoef = BleedingIndicationConstants.DROP_SIZE_END_MEDIUM;
					m_RandomSizeMin = BleedingIndicationConstants.DROP_SIZE_VARIATION_MIN_MEDIUM;
					m_RandomSizeMax = BleedingIndicationConstants.DROP_SIZE_VARIATION_MAX_MEDIUM;
					m_ScatterPx = BleedingIndicationConstants.DROP_SCATTER_MEDIUM;
					m_SlideDistance = BleedingIndicationConstants.DROP_SLIDE_DISTANCE_MEDIUM;
					break;
				}
				case BleedingIndicationConstants.INDICATOR_SEVERITY_HIGH:
				{
					m_Duration = BleedingIndicationConstants.DROP_DURATION_HIGH;
					m_StartSizeCoef = BleedingIndicationConstants.DROP_SIZE_START_HIGH;
					m_EndSizeCoef = BleedingIndicationConstants.DROP_SIZE_END_HIGH;
					m_RandomSizeMin = BleedingIndicationConstants.DROP_SIZE_VARIATION_MIN_HIGH;
					m_RandomSizeMax = BleedingIndicationConstants.DROP_SIZE_VARIATION_MAX_HIGH;
					m_ScatterPx = BleedingIndicationConstants.DROP_SCATTER_HIGH;
					m_SlideDistance = BleedingIndicationConstants.DROP_SLIDE_DISTANCE_HIGH;
					break;
				}
			}
			
			m_ProgressBreakpointTime = m_Duration * BleedingIndicationConstants.DROP_PROGRESS_THRESHOLD;
			m_ProgressBreakpoint = BleedingIndicationConstants.DROP_PROGRESS_THRESHOLD;
		}
		m_ProgressFadingDuration = Math.Max(0.0001, m_Duration - m_ProgressBreakpointTime);
		
		m_SpeedCoef = 1.0; //TODO ??
#ifdef DIAG_DEVELOPER
		if (DbgBleedingIndicationStaticInfo.m_DbgUseOverrideValues)
		{
			m_ColorAlphaStart = DbgBleedingIndicationStaticInfo.m_DbgDropColorAlphaStart / 255;
			m_ColorAlphaEnd = DbgBleedingIndicationStaticInfo.m_DbgDropColorAlphaEnd / 255;
		}
		else
#endif
		{
			m_ColorAlphaStart = BleedingIndicationConstants.DROP_COLOR_ALPHA_START / 255;
			m_ColorAlphaEnd = BleedingIndicationConstants.DROP_COLOR_ALPHA_END / 255;
		}
		InitImageScale();
		GetScreenSize(m_ScreenSizeX,m_ScreenSizeY);
		AdjustColorSaturation();
	}
	
	void ~BleedingIndicatorDropData()
	{
	}
	
	protected void InitImageScale()
	{
		m_Widget.GetSize(m_ImageBaseSizeX,m_ImageBaseSizeY);
		float randomScaleCoef =  Math.RandomFloatInclusive(m_RandomSizeMin,m_RandomSizeMax);
		
		m_ImageStartingSizeX = m_ImageBaseSizeX * m_StartSizeCoef * randomScaleCoef;
		m_ImageEndSizeX = m_ImageBaseSizeX * m_EndSizeCoef * randomScaleCoef;
		m_ImageStartingSizeY = m_ImageBaseSizeY * m_StartSizeCoef * randomScaleCoef;
		m_ImageEndSizeY = m_ImageBaseSizeY * m_EndSizeCoef * randomScaleCoef;
	}
	
	void ScatterPosition(vector pos)
	{
#ifdef DIAG_DEVELOPER
		if (DbgBleedingIndicationStaticInfo.m_DbgUseOverrideValues)
		{
			m_ScatterPx = DbgBleedingIndicationStaticInfo.m_DbgDropScatter;
		}
#endif
		float rndRadius = Math.RandomFloatInclusive(0.0,m_ScatterPx);
		float rndPos = Math.RandomFloatInclusive(0.0,Math.PI2);
		m_PosX = pos[0];
		m_PosX = m_PosX + rndRadius * Math.Sin(rndPos);
		
		m_PosY = pos[1];
		m_PosY = m_PosY + rndRadius * Math.Cos(rndPos);
	}
	
	void StartDrop()
	{
		m_TimeTotal = 0;
		
		ScatterPosition(m_BasePosition);
		m_Widget.SetPos(m_PosX,m_PosY);
#ifdef DIAG_DEVELOPER
		if (DbgBleedingIndicationStaticInfo.m_DbgUseOverrideValues && !DbgBleedingIndicationStaticInfo.m_DbgDropRotationRandom)
		{
			m_Widget.SetRotation(0,0,0);
		}
		else
#endif
		{
			m_Widget.SetRotation(0,0,Math.RandomFloatInclusive(0.0,360.0));
		}
		
		m_Widget.Show(true);
		m_IsRunning = true;
	}
	
	void StopDrop()
	{
		m_IsRunning = false;
		m_Widget.SetSize(m_ImageBaseSizeX,m_ImageBaseSizeY); //resets image size
		m_Widget.Show(false);
	}
	
	void SetBasePosition(vector pos)
	{
		m_BasePosition = pos;
		m_BasePosition[0] = m_BasePosition[0] - m_ScreenSizeX/2;
		m_BasePosition[1] = m_BasePosition[1] - m_ScreenSizeY/2;
	}
	
	bool IsRunning()
	{
		return m_IsRunning;
	}
	
	ImageWidget GetImage()
	{
		return m_Widget;
	}
	
	void AdjustColorSaturation()
	{
		//color adjustment
		float r = BleedingIndicationConstants.DROP_COLOR_RED;
		float g = BleedingIndicationConstants.DROP_COLOR_GREEN;
		float b = BleedingIndicationConstants.DROP_COLOR_BLUE;
		float desaturationEnd = BleedingIndicationConstants.DROP_COLOR_DESATURATIONEND;
#ifdef DIAG_DEVELOPER
		if (DbgBleedingIndicationStaticInfo.m_DbgUseOverrideValues)
		{
			r = DbgBleedingIndicationStaticInfo.m_DbgDropColorRed;
			g = DbgBleedingIndicationStaticInfo.m_DbgDropColorGreen;
			b = DbgBleedingIndicationStaticInfo.m_DbgDropColorBlue;
			desaturationEnd = DbgBleedingIndicationStaticInfo.m_DbgDesaturationEnd;
		}
#endif
		
		//saturation adjustment
#ifdef DIAG_DEVELOPER
		if (!DbgBleedingIndicationStaticInfo.m_DbgUseOverrideValues || (DbgBleedingIndicationStaticInfo.m_DbgUseOverrideValues && DbgBleedingIndicationStaticInfo.m_DbgDropDesaturate) )
		{
#endif
			Param par = PPEManagerStatic.GetPPEManager().GetPostProcessCurrentValues(PostProcessEffectType.Glow,PPEGlow.PARAM_SATURATION);
			float saturationProgress = Param1<float>.Cast(par).param1;
			saturationProgress = Easing.EaseOutSine(saturationProgress);
			saturationProgress = Math.Lerp(desaturationEnd,1.0,saturationProgress);
			float lowest_channel = Math.Min(Math.Min(r,g),b);
			r = Math.Lerp(lowest_channel,r,saturationProgress);
			g = Math.Lerp(lowest_channel,g,saturationProgress);
			b = Math.Lerp(lowest_channel,b,saturationProgress);
#ifdef DIAG_DEVELOPER
		}
#endif
		
		int color = ARGB(0x00,r,g,b);
		m_Widget.SetColor(color);
	}
	
	void UpdateAlpha(float progress,float progressFade)
	{
		if (progress <= m_ProgressBreakpoint)
		{
			m_ColorAlphaCurrent = m_ColorAlphaStart;
		}
		else
		{
			m_ColorAlphaCurrent = Math.Lerp(m_ColorAlphaStart,m_ColorAlphaEnd,progressFade);
		}
		
		m_Widget.SetAlpha(m_ColorAlphaCurrent);
	}
	
	//! scaling and transformation
	void UpdateTransform(float progress, float progressFade)
	{
		float breakProgress = Math.Clamp(Math.InverseLerp(0.0,m_ProgressBreakpoint,progress),0,1);
		float sizeX = Math.Lerp(m_ImageStartingSizeX,m_ImageEndSizeX,breakProgress);
		float sizeY = Math.Lerp(m_ImageStartingSizeY,m_ImageEndSizeY,breakProgress);
		m_Widget.SetSize(sizeX,sizeY);
		
		if (progress <= m_ProgressBreakpoint)
		{
			//do stuff before breakpoint
		}
		else
		{
			//do stuff after breakpoint
			float posYTemp = Math.Lerp(m_PosY,m_PosY + m_SlideDistance, progressFade);
			m_Widget.SetPos(m_PosX,posYTemp);
		}
	}
	
	void Update(float timeSlice)
	{
		if (m_IsRunning)
		{
			float progress, progressFade;
			progress = m_TimeTotal / m_Duration;
			progressFade = (m_TimeTotal - m_ProgressBreakpointTime) / m_ProgressFadingDuration;
			
			//alpha
			UpdateAlpha(progress,progressFade);
			//transform + scaling
			UpdateTransform(progress,progressFade);
			
			m_TimeTotal += (timeSlice * m_SpeedCoef);
			
			if (m_TimeTotal >= m_Duration)
			{
				//deletes this;
				StopDrop();
			}
		}
	}
}
