import class gameuiPhoneWaveformData extends IScriptable
{
	import var points : array< Vector4 >;
}

import class PhoneWaveformGameController extends inkGameController
{
	private editable var m_barItemName : CName;
	private var m_root : weak< inkCompoundWidget >;
	private var m_bars : array< weak< inkWidget > >;
	private var m_traces : array< weak< inkWidget > >;
	private var m_cachedRootSize : Vector2;
	private var m_maxValue : Float;
	default m_maxValue = 200.f;
	private var m_barsPadding : Float;
	default m_barsPadding = 4.f;
	private var m_barSize : Vector2;

	public import function SetMeasurementsCount( value : Int32 );
	public import function GetMeasurementsCount() : Int32;
	public import function SetMeasurementsIntreval( value : Float );
	public import function GetMeasurementsIntreval() : Float;

	public function SetItemName( value : CName )
	{
		m_barItemName = value;
	}

	protected event OnInitialize()
	{
		m_root = GetRootCompoundWidget();
		m_cachedRootSize = m_root.GetSize();
		InitWaveform();
	}

	protected event OnUpdate( audioData : gameuiPhoneWaveformData )
	{
		var rootSize : Vector2;
		if( m_root && m_root.IsVisible() )
		{
			rootSize = m_root.GetSize();
			if( m_cachedRootSize != rootSize )
			{
				m_cachedRootSize = rootSize;
				InitWaveform();
			}
			UpdateWaveform( audioData.points );
		}
	}

	private function InitWaveform()
	{
		var count, i : Int32;
		var margin : inkMargin;
		var bar : weak< inkWidget >;
		count = GetMeasurementsCount();
		m_barSize = Vector2( ( m_cachedRootSize.X - ( m_barsPadding * ( ( Float )( count ) ) ) ) / ( ( Float )( count ) ), m_cachedRootSize.Y );
		while( m_bars.Size() > 0 )
		{
			m_root.RemoveChild( m_bars.PopBack() );
		}
		for( i = 0; i < count; i += 1 )
		{
			margin = inkMargin( ( ( ( Float )( i ) ) * m_barSize.X ) + ( m_barsPadding * ( ( Float )( i ) ) ), m_cachedRootSize.Y, 0.0, 0.0 );
			bar = SpawnBar( margin );
			m_bars.PushBack( bar );
			bar = SpawnBar( margin );
			bar.SetOpacity( 0.5 );
			m_traces.PushBack( bar );
		}
	}

	private function SpawnBar( margin : inkMargin ) : weak< inkCompoundWidget >
	{
		var newBar : weak< inkCompoundWidget >;
		newBar = ( ( inkCompoundWidget )( SpawnFromLocal( m_root, m_barItemName ) ) );
		newBar.SetAnchorPoint( Vector2( 0.0, 1.0 ) );
		newBar.SetRenderTransformPivot( Vector2( 0.0, 1.0 ) );
		newBar.SetSize( Vector2( 0.0, 0.0 ) );
		newBar.SetMargin( margin );
		return newBar;
	}

	private function UpdateWaveform( const audioData : ref< array< Vector4 > > )
	{
		var count, i : Int32;
		var value : Float;
		var rndValue : Float;
		var size, traceSize : Vector2;
		var bar, trace : weak< inkWidget >;
		count = m_bars.Size();
		for( i = 0; i < count; i += 1 )
		{
			value = ( m_maxValue - AbsF( audioData[ i ].Z ) ) / m_maxValue;
			if( value > 0.0 )
			{
				rndValue = ( 0.75 * value ) + ( 0.25 * RandF() );
			}
			else
			{
				rndValue = 0.0;
			}
			bar = m_bars[ i ];
			trace = m_traces[ i ];
			size = FixSize( bar, rndValue );
			traceSize = trace.GetSize();
			if( size.Y > traceSize.Y )
			{
				traceSize.Y = size.Y;
				traceSize.X = size.X;
			}
			else if( traceSize.Y > 0.0 )
			{
				traceSize.Y -= 2.0;
				if( traceSize.Y < 0.0 )
				{
					traceSize.Y = 0.0;
				}
			}
			trace.SetSize( traceSize );
		}
	}

	private function FixSize( bar : weak< inkWidget >, value : Float ) : Vector2
	{
		var intX, intY : Int32;
		var res : Vector2;
		intX = RoundF( m_barSize.X );
		intY = RoundF( m_barSize.Y * value );
		if( !( FloatIsEqual( ( ( Float )( intX ) ) / 2.0, ( ( Float )( RoundF( ( ( Float )( intX ) ) / 2.0 ) ) ) ) ) )
		{
			intX += 1;
		}
		if( !( FloatIsEqual( ( ( Float )( intY ) ) / 2.0, ( ( Float )( RoundF( ( ( Float )( intY ) ) / 2.0 ) ) ) ) ) )
		{
			intY += 1;
		}
		res = Vector2( ( ( Float )( intX ) ), ( ( Float )( intY ) ) );
		bar.SetSize( res );
		return res;
	}

}

