struct CyberwareAttributes_ContainersStruct
{
	editable var widgetBody : inkWidgetRef;
	editable var widgetCool : inkWidgetRef;
	editable var widgetInt : inkWidgetRef;
	editable var widgetRef : inkWidgetRef;
	editable var widgetTech : inkWidgetRef;
	var logicBody : weak< CyberwareAttributes_Logic >;
	var logicCool : weak< CyberwareAttributes_Logic >;
	var logicInt : weak< CyberwareAttributes_Logic >;
	var logicRef : weak< CyberwareAttributes_Logic >;
	var logicTech : weak< CyberwareAttributes_Logic >;
}

struct CyberwareAttributes_ResistancesStruct
{
	editable var widgetHealth : inkFlexRef;
	editable var widgetPhysical : inkFlexRef;
	editable var widgetThermal : inkFlexRef;
	editable var widgetEMP : inkFlexRef;
	editable var widgetChemical : inkFlexRef;
	editable var resistanceTooltip : inkFlexRef;
}

class CyberwareAttributesSkills extends inkGameController
{
	protected editable var m_attributes : CyberwareAttributes_ContainersStruct;
	protected editable var m_resistances : CyberwareAttributes_ResistancesStruct;
	protected editable var m_levelUpPoints : inkTextRef;
	private var m_uiBlackboard : weak< IBlackboard >;
	private var m_playerPuppet : weak< PlayerPuppet >;
	private var m_devPoints : Int32;
	private var m_OnAttributesChangeCallback : CallbackHandle;
	private var m_OnDevelopmentPointsChangeCallback : CallbackHandle;
	private var m_OnProficiencyChangeCallback : CallbackHandle;
	private var m_OnMaxHealthChangedCallback : CallbackHandle;
	private var m_OnPhysicalResistanceChangedCallback : CallbackHandle;
	private var m_OnThermalResistanceChangedCallback : CallbackHandle;
	private var m_OnEnergyResistanceChangedCallback : CallbackHandle;
	private var m_OnChemicalResistanceChangedCallback : CallbackHandle;

	protected event OnInitialize()
	{
		var requestStatsEvent : RequestStats;
		m_playerPuppet = ( ( PlayerPuppet )( GameInstance.GetPlayerSystem( GetPlayerControlledObject().GetGame() ).GetLocalPlayerMainGameObject() ) );
		m_uiBlackboard = GetBlackboardSystem().Get( GetAllBlackboardDefs().UI_PlayerStats );
		if( m_uiBlackboard )
		{
			m_OnAttributesChangeCallback = m_uiBlackboard.RegisterListenerVariant( GetAllBlackboardDefs().UI_PlayerStats.Attributes, this, 'OnAttributesChange' );
			m_OnDevelopmentPointsChangeCallback = m_uiBlackboard.RegisterListenerVariant( GetAllBlackboardDefs().UI_PlayerStats.DevelopmentPoints, this, 'OnDevelopmentPointsChange' );
			m_OnProficiencyChangeCallback = m_uiBlackboard.RegisterListenerVariant( GetAllBlackboardDefs().UI_PlayerStats.Proficiency, this, 'OnProficiencyChange' );
			m_OnMaxHealthChangedCallback = m_uiBlackboard.RegisterListenerInt( GetAllBlackboardDefs().UI_PlayerStats.MaxHealth, this, 'OnSomeResistanceChanged' );
			m_OnPhysicalResistanceChangedCallback = m_uiBlackboard.RegisterListenerInt( GetAllBlackboardDefs().UI_PlayerStats.PhysicalResistance, this, 'OnSomeResistanceChanged' );
			m_OnThermalResistanceChangedCallback = m_uiBlackboard.RegisterListenerInt( GetAllBlackboardDefs().UI_PlayerStats.ThermalResistance, this, 'OnSomeResistanceChanged' );
			m_OnEnergyResistanceChangedCallback = m_uiBlackboard.RegisterListenerInt( GetAllBlackboardDefs().UI_PlayerStats.EnergyResistance, this, 'OnSomeResistanceChanged' );
			m_OnChemicalResistanceChangedCallback = m_uiBlackboard.RegisterListenerInt( GetAllBlackboardDefs().UI_PlayerStats.ChemicalResistance, this, 'OnSomeResistanceChanged' );
		}
		m_attributes.logicBody = ( ( CyberwareAttributes_Logic )( inkWidgetRef.GetController( m_attributes.widgetBody ) ) );
		m_attributes.logicCool = ( ( CyberwareAttributes_Logic )( inkWidgetRef.GetController( m_attributes.widgetCool ) ) );
		m_attributes.logicInt = ( ( CyberwareAttributes_Logic )( inkWidgetRef.GetController( m_attributes.widgetInt ) ) );
		m_attributes.logicRef = ( ( CyberwareAttributes_Logic )( inkWidgetRef.GetController( m_attributes.widgetRef ) ) );
		m_attributes.logicTech = ( ( CyberwareAttributes_Logic )( inkWidgetRef.GetController( m_attributes.widgetTech ) ) );
		inkFlexRef.Get( m_resistances.widgetHealth ).RegisterToCallback( 'OnButtonStateChanged', this, 'OnResistancesHover' );
		inkFlexRef.Get( m_resistances.widgetPhysical ).RegisterToCallback( 'OnButtonStateChanged', this, 'OnResistancesHover' );
		inkFlexRef.Get( m_resistances.widgetThermal ).RegisterToCallback( 'OnButtonStateChanged', this, 'OnResistancesHover' );
		inkFlexRef.Get( m_resistances.widgetEMP ).RegisterToCallback( 'OnButtonStateChanged', this, 'OnResistancesHover' );
		inkFlexRef.Get( m_resistances.widgetChemical ).RegisterToCallback( 'OnButtonStateChanged', this, 'OnResistancesHover' );
		SyncWithPlayerDevSystem();
		requestStatsEvent = new RequestStats;
		m_playerPuppet.QueueEvent( requestStatsEvent );
		inkFlexRef.Get( m_resistances.resistanceTooltip ).SetVisible( false );
		( ( inkVideo )( GetWidget( inkWidgetPath.Build( 'temp_paperdoll' ) ) ) ).Play();
	}

	private function SyncWithPlayerDevSystem()
	{
		SyncProficiencies();
		SyncStats();
		SyncDevPoints();
	}

	private function SyncProficiencies() {}

	private function HelperGetStatText( currStatType : gamedataStatType, statsSystem : StatsSystem ) : String
	{
		var currInt : Int32;
		currInt = ( ( Int32 )( statsSystem.GetStatValue( m_playerPuppet.GetEntityID(), currStatType ) ) );
		return IntToString( currInt );
	}

	private function SyncStats()
	{
		var statsSystem : StatsSystem;
		var currText : weak< inkText >;
		statsSystem = GameInstance.GetStatsSystem( m_playerPuppet.GetGame() );
		currText = ( ( inkText )( inkFlexRef.GetWidget( m_resistances.widgetHealth, inkWidgetPath.Build( 'textVert', 'resistanceText' ) ) ) );
		currText.SetText( HelperGetStatText( gamedataStatType.Health, statsSystem ) );
		currText = ( ( inkText )( inkFlexRef.GetWidget( m_resistances.widgetPhysical, inkWidgetPath.Build( 'textVert', 'resistanceText' ) ) ) );
		currText.SetText( HelperGetStatText( gamedataStatType.PhysicalResistance, statsSystem ) );
		currText = ( ( inkText )( inkFlexRef.GetWidget( m_resistances.widgetChemical, inkWidgetPath.Build( 'textVert', 'resistanceText' ) ) ) );
		currText.SetText( HelperGetStatText( gamedataStatType.ChemicalResistance, statsSystem ) );
		currText = ( ( inkText )( inkFlexRef.GetWidget( m_resistances.widgetThermal, inkWidgetPath.Build( 'textVert', 'resistanceText' ) ) ) );
		currText.SetText( HelperGetStatText( gamedataStatType.ThermalResistance, statsSystem ) );
		currText = ( ( inkText )( inkFlexRef.GetWidget( m_resistances.widgetEMP, inkWidgetPath.Build( 'textVert', 'resistanceText' ) ) ) );
		currText.SetText( HelperGetStatText( gamedataStatType.ElectricResistance, statsSystem ) );
		( ( CyberwareAttributes_Logic )( inkWidgetRef.GetController( m_attributes.widgetBody ) ) ).SetAttributeValue( HelperGetStatText( gamedataStatType.Strength, statsSystem ) );
		( ( CyberwareAttributes_Logic )( inkWidgetRef.GetController( m_attributes.widgetCool ) ) ).SetAttributeValue( HelperGetStatText( gamedataStatType.Cool, statsSystem ) );
		( ( CyberwareAttributes_Logic )( inkWidgetRef.GetController( m_attributes.widgetInt ) ) ).SetAttributeValue( HelperGetStatText( gamedataStatType.Intelligence, statsSystem ) );
		( ( CyberwareAttributes_Logic )( inkWidgetRef.GetController( m_attributes.widgetRef ) ) ).SetAttributeValue( HelperGetStatText( gamedataStatType.Reflexes, statsSystem ) );
		( ( CyberwareAttributes_Logic )( inkWidgetRef.GetController( m_attributes.widgetTech ) ) ).SetAttributeValue( HelperGetStatText( gamedataStatType.TechnicalAbility, statsSystem ) );
	}

	protected event OnSomeResistanceChanged( value : Int32 )
	{
		SyncStats();
	}

	private function SyncDevPoints()
	{
		var devSystem : PlayerDevelopmentSystem;
		devSystem = ( ( PlayerDevelopmentSystem )( GameInstance.GetScriptableSystemsContainer( m_playerPuppet.GetGame() ).Get( 'PlayerDevelopmentSystem' ) ) );
		m_devPoints = devSystem.GetDevPoints( m_playerPuppet, gamedataDevelopmentPointType.Attribute );
		inkTextRef.SetText( m_levelUpPoints, IntToString( m_devPoints ) );
	}

	protected event OnResistancesHover( controller : weak< inkButtonController >, oldState : inkEButtonState, newState : inkEButtonState )
	{
		var isHovering : Bool;
		isHovering = oldState == inkEButtonState.Normal && newState == inkEButtonState.Hover;
		inkFlexRef.Get( m_resistances.resistanceTooltip ).SetVisible( isHovering );
	}

	private function OnSpendPoints( e : inkPointerEvent )
	{
		var widgetTarget : weak< inkWidget >;
		var requestUpdateEvent : RequestStats;
		var requestBuyStatsEvent : RequestBuyAttribute;
		requestBuyStatsEvent = new RequestBuyAttribute;
		widgetTarget = e.GetTarget();
		if( widgetTarget == inkWidgetRef.Get( m_attributes.widgetRef ) )
		{
			requestBuyStatsEvent.type = gamedataStatType.Reflexes;
		}
		else if( widgetTarget == inkWidgetRef.Get( m_attributes.widgetBody ) )
		{
			requestBuyStatsEvent.type = gamedataStatType.Strength;
		}
		else if( widgetTarget == inkWidgetRef.Get( m_attributes.widgetTech ) )
		{
			requestBuyStatsEvent.type = gamedataStatType.TechnicalAbility;
		}
		else if( widgetTarget == inkWidgetRef.Get( m_attributes.widgetInt ) )
		{
			requestBuyStatsEvent.type = gamedataStatType.Intelligence;
		}
		else if( widgetTarget == inkWidgetRef.Get( m_attributes.widgetCool ) )
		{
			requestBuyStatsEvent.type = gamedataStatType.Cool;
		}
		else
		{
			requestBuyStatsEvent.type = gamedataStatType.Invalid;
		}
		m_playerPuppet.QueueEvent( requestBuyStatsEvent );
		requestUpdateEvent = new RequestStats;
		m_playerPuppet.QueueEvent( requestUpdateEvent );
	}

	protected event OnAttributesChange( value : Variant )
	{
		var i : Int32;
		var currName : gamedataStatType;
		var currValue : String;
		var attributes : array< SAttribute >;
		attributes = ( ( array< SAttribute > )value );
		for( i = 0; i < attributes.Size(); i += 1 )
		{
			currName = attributes[ i ].attributeName;
			currValue = IntToString( attributes[ i ].value );
			if( currName == gamedataStatType.Strength )
			{
				m_attributes.logicBody.SetAttributeValue( currValue );
			}
			else if( currName == gamedataStatType.Reflexes )
			{
				m_attributes.logicRef.SetAttributeValue( currValue );
			}
			else if( currName == gamedataStatType.TechnicalAbility )
			{
				m_attributes.logicTech.SetAttributeValue( currValue );
			}
			else if( currName == gamedataStatType.Intelligence )
			{
				m_attributes.logicInt.SetAttributeValue( currValue );
			}
			else if( currName == gamedataStatType.Cool )
			{
				m_attributes.logicCool.SetAttributeValue( currValue );
			}
		}
	}

	protected event OnDevelopmentPointsChange( value : Variant )
	{
		var i : Int32;
		var developmentPoints : array< SDevelopmentPoints >;
		developmentPoints = ( ( array< SDevelopmentPoints > )value );
		for( i = 0; i < developmentPoints.Size(); i += 1 )
		{
			if( developmentPoints[ i ].type == gamedataDevelopmentPointType.Attribute )
			{
				m_devPoints = developmentPoints[ i ].unspent;
				inkTextRef.SetText( m_levelUpPoints, IntToString( developmentPoints[ i ].unspent ) );
				return true;
			}
		}
	}

	protected event OnProficiencyChange( value : Variant ) {}
}

class CyberwareAttributes_Logic extends inkLogicController
{
	protected editable var m_textValue : inkTextRef;
	protected editable var m_buttonRef : inkWidgetRef;
	protected editable var m_tooltipRef : inkWidgetRef;
	protected editable var m_connectorRef : inkWidgetRef;

	protected event OnInitialize()
	{
		inkWidgetRef.SetVisible( m_tooltipRef, false );
		inkWidgetRef.SetVisible( m_connectorRef, false );
		inkWidgetRef.RegisterToCallback( m_buttonRef, 'OnHoverOver', this, 'OnButtonHoverOver' );
		inkWidgetRef.RegisterToCallback( m_buttonRef, 'OnHoverOut', this, 'OnButtonHoverOut' );
	}

	protected event OnButtonHoverOver( e : inkPointerEvent )
	{
		inkWidgetRef.SetVisible( m_tooltipRef, true );
		inkWidgetRef.SetVisible( m_connectorRef, true );
	}

	protected event OnButtonHoverOut( e : inkPointerEvent )
	{
		inkWidgetRef.SetVisible( m_tooltipRef, false );
		inkWidgetRef.SetVisible( m_connectorRef, false );
	}

	public function SetAttributeValue( const value : ref< String > )
	{
		var currGraphic : weak< inkImage >;
		inkTextRef.SetText( m_textValue, value );
		currGraphic = ( ( inkImage )( ( ( inkCanvas )( inkWidgetRef.Get( m_buttonRef ) ) ).GetWidget( inkWidgetPath.Build( 'mainRotate', 'graphic' ) ) ) );
		if( currGraphic != NULL )
		{
			currGraphic.SetTexturePart( StringToName( "barcode_" + value ) );
		}
	}

}

class RequestBuyAttribute extends Event
{
	var type : gamedataStatType;
}

