class NewItemTooltipCommonController extends AGenericTooltipControllerWithDebug
{
	protected editable var m_backgroundContainer : inkWidgetRef;
	protected editable var m_itemEquippedContainer : inkWidgetRef;
	protected editable var m_itemRecipeContainer : inkWidgetRef;
	protected editable var m_itemHeaderContainer : inkWidgetRef;
	protected editable var m_itemBrokenContainer : inkWidgetRef;
	protected editable var m_itemWeaponBarsContainer : inkWidgetRef;
	protected editable var m_itemRequirementsContainer : inkWidgetRef;
	protected editable var m_itemDetailsStatsContainer : inkWidgetRef;
	protected editable var m_itemDescriptionContainer : inkWidgetRef;
	protected editable var m_itemDetailsContainer : inkWidgetRef;
	protected editable var m_itemBottomContainer : inkWidgetRef;
	protected editable var m_cornerContainer : inkWidgetRef;
	protected editable var m_root : inkWidgetRef;
	protected editable var m_iconicBG : inkWidgetRef;
	protected editable var m_recipeBG : inkWidgetRef;
	protected editable var m_illegalBG : inkWidgetRef;
	protected editable var m_descriptionWrapper : inkWidgetRef;
	protected editable var m_descriptionText : inkTextRef;
	protected editable var DEBUG_iconErrorWrapper : inkWidgetRef;
	protected editable var DEBUG_iconErrorText : inkTextRef;
	protected const editable var m_frames : array< inkWidgetRef >;
	protected var m_spawnedModules : array< weak< NewItemTooltipModuleController > >;
	protected var m_itemEquippedController : weak< NewItemTooltipEquippedModule >;
	protected var m_itemRecipeController : weak< NewItemTooltipRepiceModule >;
	protected var m_itemHeaderController : weak< NewItemTooltipHeaderController >;
	protected var m_itemBrokenController : weak< NewItemTooltipBrokenModule >;
	protected var m_itemWeaponBarsController : weak< NewItemTooltipWeaponBarsModule >;
	protected var m_itemRequirementsController : weak< NewItemTooltipRequirementsModule >;
	protected var m_itemDetailsStatsController : weak< NewItemTooltipDetailsStatsModule >;
	protected var m_itemDescriptionController : weak< NewItemTooltipDescriptionModule >;
	protected var m_itemDetailsController : weak< NewItemTooltipDetailsModule >;
	protected var m_itemBottomController : weak< NewItemTooltipBottomModule >;
	protected var DEBUG_showAdditionalInfo : Bool;
	protected var m_data : MinimalItemTooltipData;
	protected var m_itemData : UIInventoryItem;
	protected var m_comparisonData : UIInventoryItemComparisonManager;
	protected var m_player : weak< PlayerPuppet >;
	protected var m_requestedModules : array< CName >;
	protected var m_pendingModules : array< CName >;
	protected var m_displayContext : ItemDisplayContextData;
	protected var m_tooltipDisplayContext : InventoryTooltipDisplayContext;
	protected var m_itemDisplayContext : ItemDisplayContext;
	protected var m_priceOverride : Int32;
	protected var m_settings : UserSettings;
	protected var m_settingsListener : NewItemTooltipSettingsListener;
	protected var m_groupPath : CName;
	default m_groupPath = '/accessibility/interface';
	protected editable var m_minWidth : inkWidgetRef;
	protected var m_bigFontEnabled : Bool;
	protected var m_inCrafting : Bool;

	public function SetData( const data : ref< ItemViewData > )
	{
		SetData( InventoryTooltipData.FromItemViewData( data ) );
	}

	public override function SetData( tooltipData : ATooltipData )
	{
		var tooltipWrapper : UIInventoryItemTooltipWrapper;
		m_comparisonData = NULL;
		if( ( ( InventoryTooltipData )( tooltipData ) ) )
		{
			UpdateData( ( ( InventoryTooltipData )( tooltipData ) ) );
		}
		else if( ( ( UIInventoryItemTooltipWrapper )( tooltipData ) ) )
		{
			tooltipWrapper = ( ( UIInventoryItemTooltipWrapper )( tooltipData ) );
			m_itemData = tooltipWrapper.m_data;
			m_comparisonData = tooltipWrapper.m_comparisonData;
			m_displayContext = tooltipWrapper.m_displayContext;
			m_player = tooltipWrapper.m_displayContext.GetPlayerAsPuppet();
			m_itemDisplayContext = tooltipWrapper.m_displayContext.GetDisplayContext();
			m_tooltipDisplayContext = tooltipWrapper.m_displayContext.GetTooltipDisplayContext();
			m_inCrafting = m_tooltipDisplayContext == InventoryTooltipDisplayContext.Crafting || m_tooltipDisplayContext == InventoryTooltipDisplayContext.Upgrading;
			m_priceOverride = tooltipWrapper.m_overridePrice;
			InvalidateSpawnedModules();
			RegisterUserSettingsListener();
			NewUpdateTooltipSize();
			NEW_UpdateLayout();
		}
		else
		{
			m_data = ( ( MinimalItemTooltipData )( tooltipData ) );
			m_displayContext = m_data.displayContextData;
			m_inCrafting = m_data.displayContext == InventoryTooltipDisplayContext.Crafting || m_data.displayContext == InventoryTooltipDisplayContext.Upgrading;
			RegisterUserSettingsListener();
			NewUpdateTooltipSize();
			UpdateLayout();
		}
		DEBUG_UpdateDebugInfo();
	}

	public function UpdateData( tooltipData : InventoryTooltipData )
	{
		m_data = MinimalItemTooltipData.FromInventoryTooltipData( tooltipData );
		m_inCrafting = m_data.displayContext == InventoryTooltipDisplayContext.Crafting || m_data.displayContext == InventoryTooltipDisplayContext.Upgrading;
		RegisterUserSettingsListener();
		NewUpdateTooltipSize();
		UpdateLayout();
	}

	public override function PrespawnLazyModules()
	{
		RequestModule( m_itemEquippedContainer, 'itemEquipped', 'OnNEW_EquippedModuleSpawned' );
		RequestModule( m_itemRecipeContainer, 'itemRecipe', 'OnNEW_RecipeModuleSpawned' );
		RequestModule( m_itemHeaderContainer, 'itemHeader', 'OnNEW_HeaderModuleSpawned' );
		RequestModule( m_itemWeaponBarsContainer, 'itemWeaponBars', 'OnNEW_WeaponBarsModuleSpawned' );
		RequestModule( m_itemDetailsStatsContainer, 'itemDetailsStats', 'OnNEW_DetailsStatsModuleSpawned' );
		RequestModule( m_itemDescriptionContainer, 'itemDescription', 'OnNEW_DescriptionModuleSpawned' );
		RequestModule( m_itemRequirementsContainer, 'itemRequirements', 'OnNEW_RequirementsModuleSpawned' );
		RequestModule( m_itemDetailsContainer, 'itemDetails', 'OnNEW_DetailsModuleSpawned' );
		RequestModule( m_itemBottomContainer, 'itemBottom', 'OnNEW_BottomModuleSpawned' );
		RequestModule( m_itemBrokenContainer, 'itemBroken', 'OnNEW_BrokenModuleSpawned' );
	}

	protected function RequestModule( container : inkWidgetRef, moduleName : CName, callback : CName, optional data : NewItemTooltipModuleSpawnedCallbackData ) : Bool
	{
		var spawnedCallbackData : NewItemTooltipModuleSpawnedCallbackData;
		if( m_requestedModules.Contains( moduleName ) )
		{
			return false;
		}
		if( data )
		{
			spawnedCallbackData = data;
		}
		else
		{
			spawnedCallbackData = new NewItemTooltipModuleSpawnedCallbackData;
			spawnedCallbackData.moduleName = moduleName;
		}
		m_requestedModules.PushBack( moduleName );
		m_pendingModules.PushBack( moduleName );
		AsyncSpawnFromLocal( inkWidgetRef.Get( container ), moduleName, this, callback, spawnedCallbackData );
		return true;
	}

	protected function HandleModuleSpawned( widget : weak< inkWidget >, data : NewItemTooltipModuleSpawnedCallbackData )
	{
		var controller : weak< NewItemTooltipModuleController >;
		m_pendingModules.Remove( data.moduleName );
		widget.SetVAlign( inkEVerticalAlign.Top );
		controller = ( ( weak< weak< NewItemTooltipModuleController > > )( widget.GetController() ) );
		m_spawnedModules.PushBack( controller );
		controller.SetDisplayContext( m_itemDisplayContext, m_tooltipDisplayContext, m_displayContext );
	}

	protected function InvalidateSpawnedModules()
	{
		var i, limit : Int32;
		for( i = 0, limit = m_spawnedModules.Size(); i < limit; i += 1 )
		{
			m_spawnedModules[ i ].SetDisplayContext( m_itemDisplayContext, m_tooltipDisplayContext, m_displayContext );
		}
	}

	protected virtual function UpdateLayout()
	{
		UpdateEquippedModule();
		UpdateRecipeModule();
		UpdateHeaderModule();
		UpdateWeaponBarsModule();
		UpdateDetailsStatsModule();
		UpdateDescriptionModule();
		UpdateRequirementsModule();
		UpdateDetailsModule();
		UpdateBottomModule();
		UpdateFramesVisibility();
		UpdateIconicBG();
		UpdateRecipeBG();
		UpdateIllegalBG();
		UpdateBrokenModule();
	}

	protected virtual function UpdateBrokenModule()
	{
		if( !( m_itemBrokenController ) )
		{
			RequestModule( m_itemBrokenContainer, 'itemBroken', 'OnBrokenModuleSpawned' );
			return;
		}
		UpdateBrokenController();
	}

	protected event OnBrokenModuleSpawned( widget : inkWidget, userData : IScriptable )
	{
		m_itemBrokenController = ( ( NewItemTooltipBrokenModule )( widget.GetController() ) );
		HandleModuleSpawned( widget, ( ( NewItemTooltipModuleSpawnedCallbackData )( userData ) ) );
		UpdateBrokenController();
	}

	private function UpdateBrokenController()
	{
		var isBroken : Bool;
		isBroken = m_data.isBroken;
		inkWidgetRef.SetVisible( m_itemBrokenContainer, isBroken );
		if( m_itemBrokenController && isBroken )
		{
			m_itemBrokenController.Update( m_data );
			m_itemBrokenController.NEW_UpdateWrapping( m_bigFontEnabled );
			inkWidgetRef.SetVisible( m_itemEquippedContainer, false );
			inkWidgetRef.SetVisible( m_itemWeaponBarsContainer, false );
			inkWidgetRef.SetVisible( m_itemDetailsStatsContainer, false );
			inkWidgetRef.SetVisible( m_itemDescriptionContainer, false );
			inkWidgetRef.SetVisible( m_itemDetailsContainer, false );
			inkWidgetRef.SetVisible( m_itemBottomContainer, false );
			inkWidgetRef.SetVisible( m_itemRequirementsContainer, false );
		}
	}

	protected function UpdateFramesVisibility()
	{
		var i : Int32;
		var isEnabled : Bool;
		isEnabled = m_data.displayContext != InventoryTooltipDisplayContext.Crafting;
		for( i = 0; i < m_frames.Size(); i += 1 )
		{
			inkWidgetRef.SetVisible( m_frames[ i ], isEnabled );
		}
	}

	protected virtual function UpdateIconicBG()
	{
		if( m_data.isIconic == true )
		{
			inkWidgetRef.SetVisible( m_iconicBG, true );
		}
		else
		{
			inkWidgetRef.SetVisible( m_iconicBG, false );
		}
	}

	protected virtual function UpdateRecipeBG()
	{
		if( m_data.itemData.HasTag( 'Recipe' ) == true )
		{
			inkWidgetRef.SetVisible( m_recipeBG, true );
		}
		else
		{
			inkWidgetRef.SetVisible( m_recipeBG, false );
		}
	}

	protected virtual function UpdateIllegalBG()
	{
		if( m_data.itemData.HasTag( 'IllegalItem' ) == true )
		{
			inkWidgetRef.SetVisible( m_illegalBG, true );
		}
		else
		{
			inkWidgetRef.SetVisible( m_illegalBG, false );
		}
	}

	protected virtual function UpdateEquippedModule()
	{
		if( m_data.isEquipped && ( m_data.displayContext != InventoryTooltipDisplayContext.Crafting && m_data.displayContext != InventoryTooltipDisplayContext.Upgrading ) )
		{
			if( !( m_itemEquippedController ) )
			{
				RequestModule( m_itemEquippedContainer, 'itemEquipped', 'OnEquippedModuleSpawned' );
				return;
			}
			inkWidgetRef.SetVisible( m_itemEquippedContainer, true );
			inkWidgetRef.SetVisible( m_cornerContainer, true );
			inkWidgetRef.SetState( m_root, 'Equipped' );
			m_itemEquippedController.Update( m_data );
		}
		else
		{
			inkWidgetRef.SetVisible( m_itemEquippedContainer, false );
			inkWidgetRef.SetVisible( m_cornerContainer, false );
			inkWidgetRef.SetState( m_root, 'Default' );
		}
	}

	protected event OnEquippedModuleSpawned( widget : inkWidget, userData : IScriptable )
	{
		m_itemEquippedController = ( ( NewItemTooltipEquippedModule )( widget.GetController() ) );
		HandleModuleSpawned( widget, ( ( NewItemTooltipModuleSpawnedCallbackData )( userData ) ) );
		UpdateEquippedModule();
	}

	protected virtual function UpdateRecipeModule()
	{
		if( m_data.itemData.HasTag( 'Recipe' ) == true && ( m_tooltipDisplayContext != InventoryTooltipDisplayContext.Crafting && m_tooltipDisplayContext != InventoryTooltipDisplayContext.Upgrading ) )
		{
			if( !( m_itemRecipeController ) )
			{
				RequestModule( m_itemRecipeContainer, 'itemRecipe', 'OnRecipeModuleSpawned' );
				return;
			}
			inkWidgetRef.SetVisible( m_itemRecipeContainer, true );
			m_itemRecipeController.Update( m_data );
		}
		else
		{
			inkWidgetRef.SetVisible( m_itemRecipeContainer, false );
		}
	}

	protected event OnRecipeModuleSpawned( widget : inkWidget, userData : IScriptable )
	{
		m_itemRecipeController = ( ( NewItemTooltipRepiceModule )( widget.GetController() ) );
		HandleModuleSpawned( widget, ( ( NewItemTooltipModuleSpawnedCallbackData )( userData ) ) );
		UpdateRecipeModule();
	}

	protected virtual function UpdateHeaderModule()
	{
		if( !( m_itemHeaderController ) )
		{
			RequestModule( m_itemHeaderContainer, 'itemHeader', 'OnHeaderModuleSpawned' );
			return;
		}
		m_itemHeaderController.Update( m_data );
		if( !( m_inCrafting ) )
		{
			m_itemHeaderController.NEW_UpdateWrapping( m_bigFontEnabled );
		}
	}

	protected event OnHeaderModuleSpawned( widget : inkWidget, userData : IScriptable )
	{
		m_itemHeaderController = ( ( NewItemTooltipHeaderController )( widget.GetController() ) );
		HandleModuleSpawned( widget, ( ( NewItemTooltipModuleSpawnedCallbackData )( userData ) ) );
		UpdateHeaderModule();
	}

	protected virtual function UpdateWeaponBarsModule()
	{
		if( ( m_data.equipmentArea == gamedataEquipmentArea.Weapon || m_data.equipmentArea == gamedataEquipmentArea.WeaponHeavy ) || RPGManager.IsItemTypeCyberwareWeapon( m_data.itemType ) )
		{
			if( !( m_itemWeaponBarsController ) )
			{
				RequestModule( m_itemWeaponBarsContainer, 'itemWeaponBars', 'OnWeaponBarsModuleSpawned' );
				return;
			}
			inkWidgetRef.SetVisible( m_itemWeaponBarsContainer, true );
			m_itemWeaponBarsController.Update( m_data );
			if( !( m_inCrafting ) )
			{
				m_itemWeaponBarsController.UpdateWrapping( m_bigFontEnabled, m_data );
			}
		}
		else
		{
			inkWidgetRef.SetVisible( m_itemWeaponBarsContainer, false );
		}
	}

	protected event OnWeaponBarsModuleSpawned( widget : inkWidget, userData : IScriptable )
	{
		m_itemWeaponBarsController = ( ( NewItemTooltipWeaponBarsModule )( widget.GetController() ) );
		HandleModuleSpawned( widget, ( ( NewItemTooltipModuleSpawnedCallbackData )( userData ) ) );
		UpdateWeaponBarsModule();
	}

	protected virtual function UpdateDetailsStatsModule()
	{
		if( m_data.GetStatsManager().SizeTooltipStats() > 0 )
		{
			if( !( m_itemDetailsStatsController ) )
			{
				RequestModule( m_itemDetailsStatsContainer, 'itemDetailsStats', 'OnDetailsStatsModuleSpawned' );
				return;
			}
			inkWidgetRef.SetVisible( m_itemDetailsStatsContainer, true );
			m_itemDetailsStatsController.GetContext( m_inCrafting );
			m_itemDetailsStatsController.Update( m_data );
		}
		else
		{
			inkWidgetRef.SetVisible( m_itemDetailsStatsContainer, false );
		}
	}

	protected event OnDetailsStatsModuleSpawned( widget : inkWidget, userData : IScriptable )
	{
		m_itemDetailsStatsController = ( ( NewItemTooltipDetailsStatsModule )( widget.GetController() ) );
		HandleModuleSpawned( widget, ( ( NewItemTooltipModuleSpawnedCallbackData )( userData ) ) );
		UpdateDetailsStatsModule();
	}

	protected virtual function UpdateDescriptionModule()
	{
		if( m_data.gameplayDescription != "" )
		{
			if( !( m_itemDescriptionController ) )
			{
				RequestModule( m_itemDescriptionContainer, 'itemDescription', 'OnDescriptionModuleSpawned' );
				return;
			}
			inkWidgetRef.SetVisible( m_itemDescriptionContainer, true );
			m_itemDescriptionController.Update( m_data );
			if( !( m_inCrafting ) )
			{
				m_itemDescriptionController.UpdateWrapping( m_bigFontEnabled );
			}
		}
		else
		{
			inkWidgetRef.SetVisible( m_itemDescriptionContainer, false );
		}
	}

	protected event OnDescriptionModuleSpawned( widget : inkWidget, userData : IScriptable )
	{
		m_itemDescriptionController = ( ( NewItemTooltipDescriptionModule )( widget.GetController() ) );
		HandleModuleSpawned( widget, ( ( NewItemTooltipModuleSpawnedCallbackData )( userData ) ) );
		UpdateDescriptionModule();
	}

	protected virtual function UpdateRequirementsModule()
	{
		if( m_data.requirements.isSmartlinkRequirementNotMet )
		{
			if( !( m_itemRequirementsController ) )
			{
				RequestModule( m_itemRequirementsContainer, 'itemRequirements', 'OnRequirementsModuleSpawned' );
				return;
			}
			inkWidgetRef.SetVisible( m_itemRequirementsContainer, true );
			m_itemRequirementsController.Update( m_data );
		}
		else
		{
			inkWidgetRef.SetVisible( m_itemRequirementsContainer, false );
		}
	}

	protected event OnRequirementsModuleSpawned( widget : inkWidget, userData : IScriptable )
	{
		m_itemRequirementsController = ( ( NewItemTooltipRequirementsModule )( widget.GetController() ) );
		HandleModuleSpawned( widget, ( ( NewItemTooltipModuleSpawnedCallbackData )( userData ) ) );
		UpdateRequirementsModule();
	}

	protected virtual function UpdateDetailsModule()
	{
		var hasDedicatedMods, hasMods : Bool;
		var isWeaponInCrafting, isWeaponOnHud, showInCrafting, showOutsideCraftingAndHud, showInHud : Bool;
		hasDedicatedMods = m_data.dedicatedMods.Size() > 0;
		hasMods = ( m_data.mods.Size() > 0 ) && m_data.displayContext != InventoryTooltipDisplayContext.Upgrading;
		isWeaponOnHud = m_data.displayContext == InventoryTooltipDisplayContext.HUD && m_data.equipmentArea == gamedataEquipmentArea.Weapon;
		isWeaponInCrafting = m_data.displayContext == InventoryTooltipDisplayContext.Crafting && m_data.equipmentArea == gamedataEquipmentArea.Weapon;
		showInCrafting = isWeaponInCrafting && ( hasDedicatedMods || hasMods );
		showOutsideCraftingAndHud = ( !( isWeaponInCrafting ) && !( isWeaponOnHud ) ) && ( hasDedicatedMods || hasMods );
		showInHud = isWeaponOnHud && ( hasDedicatedMods || hasMods );
		if( ( showOutsideCraftingAndHud || showInCrafting ) || showInHud )
		{
			if( !( m_itemDetailsController ) )
			{
				RequestModule( m_itemDetailsContainer, 'itemDetails', 'OnDetailsModuleSpawned' );
				return;
			}
			inkWidgetRef.SetVisible( m_itemDetailsContainer, true );
			m_itemDetailsController.Update( m_data, hasDedicatedMods, hasMods );
			if( !( m_inCrafting ) )
			{
				m_itemDetailsController.GetContext( m_inCrafting );
				m_itemDetailsController.NEW_UpdateWrapping( m_bigFontEnabled );
			}
		}
		else
		{
			inkWidgetRef.SetVisible( m_itemDetailsContainer, false );
		}
	}

	protected event OnDetailsModuleSpawned( widget : inkWidget, userData : IScriptable )
	{
		m_itemDetailsController = ( ( NewItemTooltipDetailsModule )( widget.GetController() ) );
		HandleModuleSpawned( widget, ( ( NewItemTooltipModuleSpawnedCallbackData )( userData ) ) );
		UpdateDetailsModule();
	}

	protected virtual function UpdateBottomModule()
	{
		if( ( m_data.displayContext == InventoryTooltipDisplayContext.Crafting || m_data.itemType == gamedataItemType.Wea_Fists ) || m_inCrafting )
		{
			inkWidgetRef.SetVisible( m_itemBottomContainer, false );
			return;
		}
		if( !( m_itemBottomController ) )
		{
			RequestModule( m_itemBottomContainer, 'itemBottom', 'OnBottomModuleSpawned' );
			return;
		}
		inkWidgetRef.SetVisible( m_itemBottomContainer, true );
		m_itemBottomController.Update( m_data );
	}

	protected event OnBottomModuleSpawned( widget : inkWidget, userData : IScriptable )
	{
		m_itemBottomController = ( ( NewItemTooltipBottomModule )( widget.GetController() ) );
		HandleModuleSpawned( widget, ( ( NewItemTooltipModuleSpawnedCallbackData )( userData ) ) );
		UpdateBottomModule();
	}

	private function NEW_UpdateLayout()
	{
		NEW_UpdateEquippedModule();
		NEW_UpdateRecipeModule();
		NEW_UpdateHeaderModule();
		NEW_UpdateWeaponBarsModule();
		NEW_UpdateDetailsStatsModule();
		NEW_UpdateDescriptionModule();
		NEW_UpdateRequirementsModule();
		NEW_UpdateDetailsModule();
		NEW_UpdateBottomModule();
		NEW_UpdateBrokenModule();
		NEW_UpdateIconicBG();
		NEW_UpdateRecipeBG();
		NEW_UpdateIllegalBG();
	}

	protected virtual function NEW_UpdateEquippedModule()
	{
		if( ( !( m_itemData.IsBroken() ) && m_itemData.IsEquipped() ) && ( m_tooltipDisplayContext != InventoryTooltipDisplayContext.Crafting && m_tooltipDisplayContext != InventoryTooltipDisplayContext.Upgrading ) )
		{
			if( !( m_itemEquippedController ) )
			{
				RequestModule( m_itemEquippedContainer, 'itemEquipped', 'OnNEW_EquippedModuleSpawned' );
				return;
			}
			inkWidgetRef.SetVisible( m_itemEquippedContainer, true );
			inkWidgetRef.SetVisible( m_cornerContainer, true );
			inkWidgetRef.SetState( m_root, 'Equipped' );
			m_itemEquippedController.NEW_Update( m_itemData );
		}
		else
		{
			inkWidgetRef.SetVisible( m_itemEquippedContainer, false );
			inkWidgetRef.SetVisible( m_cornerContainer, false );
			inkWidgetRef.SetState( m_root, 'Default' );
		}
	}

	protected event OnNEW_EquippedModuleSpawned( widget : inkWidget, userData : IScriptable )
	{
		m_itemEquippedController = ( ( NewItemTooltipEquippedModule )( widget.GetController() ) );
		HandleModuleSpawned( widget, ( ( NewItemTooltipModuleSpawnedCallbackData )( userData ) ) );
		NEW_UpdateEquippedModule();
	}

	protected virtual function NEW_UpdateRecipeModule()
	{
		if( m_itemData.IsRecipe() && ( m_tooltipDisplayContext != InventoryTooltipDisplayContext.Crafting && m_tooltipDisplayContext != InventoryTooltipDisplayContext.Upgrading ) )
		{
			if( !( m_itemRecipeController ) )
			{
				RequestModule( m_itemRecipeContainer, 'itemRecipe', 'OnNEW_RecipeModuleSpawned' );
				return;
			}
			inkWidgetRef.SetVisible( m_itemRecipeContainer, true );
			m_itemRecipeController.NEW_Update( m_itemData );
		}
		else
		{
			inkWidgetRef.SetVisible( m_itemRecipeContainer, false );
		}
	}

	protected event OnNEW_RecipeModuleSpawned( widget : inkWidget, userData : IScriptable )
	{
		m_itemRecipeController = ( ( NewItemTooltipRepiceModule )( widget.GetController() ) );
		HandleModuleSpawned( widget, ( ( NewItemTooltipModuleSpawnedCallbackData )( userData ) ) );
		NEW_UpdateRecipeModule();
	}

	protected virtual function NEW_UpdateIconicBG()
	{
		if( m_itemData.IsIconic() == true )
		{
			inkWidgetRef.SetVisible( m_iconicBG, true );
		}
		else
		{
			inkWidgetRef.SetVisible( m_iconicBG, false );
		}
	}

	protected virtual function NEW_UpdateRecipeBG()
	{
		if( m_itemData.IsRecipe() )
		{
			inkWidgetRef.SetVisible( m_recipeBG, true );
		}
		else
		{
			inkWidgetRef.SetVisible( m_recipeBG, false );
		}
	}

	protected virtual function NEW_UpdateIllegalBG()
	{
		if( m_itemData.IsIllegal() )
		{
			inkWidgetRef.SetVisible( m_illegalBG, true );
		}
		else
		{
			inkWidgetRef.SetVisible( m_illegalBG, false );
		}
	}

	protected virtual function NEW_UpdateHeaderModule()
	{
		if( !( m_itemHeaderController ) )
		{
			RequestModule( m_itemHeaderContainer, 'itemHeader', 'OnNEW_HeaderModuleSpawned' );
			return;
		}
		m_itemHeaderController.NEW_Update( m_itemData, m_comparisonData );
		if( !( m_inCrafting ) )
		{
			m_itemHeaderController.NEW_UpdateWrapping( m_bigFontEnabled );
		}
	}

	protected event OnNEW_HeaderModuleSpawned( widget : inkWidget, userData : IScriptable )
	{
		m_itemHeaderController = ( ( NewItemTooltipHeaderController )( widget.GetController() ) );
		HandleModuleSpawned( widget, ( ( NewItemTooltipModuleSpawnedCallbackData )( userData ) ) );
		NEW_UpdateHeaderModule();
	}

	protected virtual function NEW_UpdateWeaponBarsModule()
	{
		if( !( m_itemData.IsBroken() ) && m_itemData.IsWeapon() )
		{
			if( !( m_itemWeaponBarsController ) )
			{
				RequestModule( m_itemWeaponBarsContainer, 'itemWeaponBars', 'OnNEW_WeaponBarsModuleSpawned' );
				return;
			}
			inkWidgetRef.SetVisible( m_itemWeaponBarsContainer, true );
			m_itemWeaponBarsController.NEW_Update( m_itemData, m_comparisonData );
			if( !( m_inCrafting ) )
			{
				m_itemWeaponBarsController.NEW_UpdateWrapping( m_bigFontEnabled );
			}
		}
		else
		{
			inkWidgetRef.SetVisible( m_itemWeaponBarsContainer, false );
		}
	}

	protected event OnNEW_WeaponBarsModuleSpawned( widget : inkWidget, userData : IScriptable )
	{
		m_itemWeaponBarsController = ( ( NewItemTooltipWeaponBarsModule )( widget.GetController() ) );
		HandleModuleSpawned( widget, ( ( NewItemTooltipModuleSpawnedCallbackData )( userData ) ) );
		NEW_UpdateWeaponBarsModule();
	}

	protected virtual function NEW_UpdateDetailsStatsModule()
	{
		if( !( m_itemData.IsBroken() ) && ( m_itemData.GetStatsManager().SizeTooltipStats() > 0 ) )
		{
			if( !( m_itemDetailsStatsController ) )
			{
				RequestModule( m_itemDetailsStatsContainer, 'itemDetailsStats', 'OnNEW_DetailsStatsModuleSpawned' );
				return;
			}
			inkWidgetRef.SetVisible( m_itemDetailsStatsContainer, true );
			m_itemDetailsStatsController.GetContext( m_inCrafting );
			m_itemDetailsStatsController.NEW_Update( m_itemData );
		}
		else
		{
			inkWidgetRef.SetVisible( m_itemDetailsStatsContainer, false );
		}
	}

	protected event OnNEW_DetailsStatsModuleSpawned( widget : inkWidget, userData : IScriptable )
	{
		m_itemDetailsStatsController = ( ( NewItemTooltipDetailsStatsModule )( widget.GetController() ) );
		HandleModuleSpawned( widget, ( ( NewItemTooltipModuleSpawnedCallbackData )( userData ) ) );
		NEW_UpdateDetailsStatsModule();
	}

	protected virtual function NEW_UpdateDescriptionModule()
	{
		var description : String;
		description = m_itemData.GetGameplayDescription();
		if( ( !( m_itemData.IsBroken() ) && description != "None" ) && m_data.displayContext != InventoryTooltipDisplayContext.Upgrading )
		{
			if( !( m_itemDescriptionController ) )
			{
				RequestModule( m_itemDescriptionContainer, 'itemDescription', 'OnNEW_DescriptionModuleSpawned' );
				return;
			}
			inkWidgetRef.SetVisible( m_itemDescriptionContainer, true );
			m_itemDescriptionController.NEW_Update( m_itemData );
			if( !( m_inCrafting ) )
			{
				m_itemDescriptionController.UpdateWrapping( m_bigFontEnabled );
			}
		}
		else
		{
			inkWidgetRef.SetVisible( m_itemDescriptionContainer, false );
		}
	}

	protected event OnNEW_DescriptionModuleSpawned( widget : inkWidget, userData : IScriptable )
	{
		m_itemDescriptionController = ( ( NewItemTooltipDescriptionModule )( widget.GetController() ) );
		HandleModuleSpawned( widget, ( ( NewItemTooltipModuleSpawnedCallbackData )( userData ) ) );
		NEW_UpdateDescriptionModule();
	}

	protected virtual function NEW_UpdateRequirementsModule()
	{
		if( !( m_itemData.GetRequirementsManager( m_player ).IsSmartlinkRequirementMet() ) )
		{
			if( !( m_itemRequirementsController ) )
			{
				RequestModule( m_itemRequirementsContainer, 'itemRequirements', 'OnNEW_RequirementsModuleSpawned' );
				return;
			}
			inkWidgetRef.SetVisible( m_itemRequirementsContainer, true );
			m_itemRequirementsController.NEW_Update( m_itemData, m_player );
		}
		else
		{
			inkWidgetRef.SetVisible( m_itemRequirementsContainer, false );
		}
	}

	protected event OnNEW_RequirementsModuleSpawned( widget : inkWidget, userData : IScriptable )
	{
		m_itemRequirementsController = ( ( NewItemTooltipRequirementsModule )( widget.GetController() ) );
		HandleModuleSpawned( widget, ( ( NewItemTooltipModuleSpawnedCallbackData )( userData ) ) );
		NEW_UpdateRequirementsModule();
	}

	protected virtual function NEW_UpdateDetailsModule()
	{
		var modsManager : weak< UIInventoryItemModsManager >;
		var isBroken, isWeapon, hasDedicatedMods, hasMods : Bool;
		var isWeaponInCrafting, isWeaponOnHud, showInCrafting, showOutsideCraftingAndHud, showInHud : Bool;
		isBroken = m_itemData.IsBroken();
		if( !( isBroken ) )
		{
			modsManager = m_itemData.GetModsManager();
			hasDedicatedMods = modsManager.GetDedicatedMod() != NULL;
			hasMods = ( modsManager.GetModsSize() > 0 ) && m_data.displayContext != InventoryTooltipDisplayContext.Upgrading;
			isWeapon = m_itemData.IsWeapon();
			isWeaponOnHud = m_tooltipDisplayContext == InventoryTooltipDisplayContext.HUD && isWeapon;
			isWeaponInCrafting = m_tooltipDisplayContext == InventoryTooltipDisplayContext.Crafting && isWeapon;
			showInCrafting = isWeaponInCrafting && ( hasDedicatedMods || hasMods );
			showOutsideCraftingAndHud = ( !( isWeaponInCrafting ) && !( isWeaponOnHud ) ) && ( hasDedicatedMods || hasMods );
			showInHud = isWeaponOnHud && ( hasDedicatedMods || hasMods );
		}
		if( !( isBroken ) && ( ( showOutsideCraftingAndHud || showInCrafting ) || showInHud ) )
		{
			if( !( m_itemDetailsController ) )
			{
				RequestModule( m_itemDetailsContainer, 'itemDetails', 'OnNEW_DetailsModuleSpawned' );
				return;
			}
			inkWidgetRef.SetVisible( m_itemDetailsContainer, true );
			m_itemDetailsController.NEW_Update( m_itemData, m_comparisonData, hasDedicatedMods, hasMods );
			if( !( m_inCrafting ) )
			{
				m_itemDetailsController.GetContext( m_inCrafting );
				m_itemDetailsController.NEW_UpdateWrapping( m_bigFontEnabled );
			}
			return;
		}
		inkWidgetRef.SetVisible( m_itemDetailsContainer, false );
	}

	protected event OnNEW_DetailsModuleSpawned( widget : inkWidget, userData : IScriptable )
	{
		m_itemDetailsController = ( ( NewItemTooltipDetailsModule )( widget.GetController() ) );
		HandleModuleSpawned( widget, ( ( NewItemTooltipModuleSpawnedCallbackData )( userData ) ) );
		NEW_UpdateDetailsModule();
	}

	protected virtual function NEW_UpdateBottomModule()
	{
		var shouldHideBottom : Bool;
		if( ( ( ( m_itemData.IsBroken() || m_itemData.GetItemType() == gamedataItemType.Wea_HeavyMachineGun ) || !( m_itemData.IsWeapon() ) ) || m_itemData.GetItemType() == gamedataItemType.Wea_Fists ) || m_inCrafting )
		{
			shouldHideBottom = true;
		}
		if( !( shouldHideBottom ) )
		{
			if( !( m_itemBottomController ) )
			{
				RequestModule( m_itemBottomContainer, 'itemBottom', 'OnNEW_BottomModuleSpawned' );
				return;
			}
			inkWidgetRef.SetVisible( m_itemBottomContainer, true );
			m_itemBottomController.NEW_Update( m_itemData, m_player, m_priceOverride );
		}
		else
		{
			inkWidgetRef.SetVisible( m_itemBottomContainer, false );
		}
	}

	protected event OnNEW_BottomModuleSpawned( widget : inkWidget, userData : IScriptable )
	{
		m_itemBottomController = ( ( NewItemTooltipBottomModule )( widget.GetController() ) );
		HandleModuleSpawned( widget, ( ( NewItemTooltipModuleSpawnedCallbackData )( userData ) ) );
		NEW_UpdateBottomModule();
	}

	protected virtual function NEW_UpdateBrokenModule()
	{
		if( m_itemData.IsBroken() )
		{
			if( !( m_itemBrokenController ) )
			{
				RequestModule( m_itemBrokenContainer, 'itemBroken', 'OnNEW_BrokenModuleSpawned' );
				return;
			}
			inkWidgetRef.SetVisible( m_itemBrokenContainer, true );
			m_itemBrokenController.NEW_UpdateWrapping( m_bigFontEnabled );
			inkWidgetRef.SetVisible( m_itemRequirementsContainer, false );
		}
		else
		{
			inkWidgetRef.SetVisible( m_itemBrokenContainer, false );
		}
	}

	protected event OnNEW_BrokenModuleSpawned( widget : inkWidget, userData : IScriptable )
	{
		m_itemBrokenController = ( ( NewItemTooltipBrokenModule )( widget.GetController() ) );
		HandleModuleSpawned( widget, ( ( NewItemTooltipModuleSpawnedCallbackData )( userData ) ) );
		NEW_UpdateBrokenModule();
	}

	protected override function DEBUG_UpdateDebugInfo()
	{
		var craftableItems : array< weak< Item_Record > >;
		var recipeRecord : RecipeItem_Record;
		var resultText : String;
		var errorData : DEBUG_IconErrorInfo;
		var iconsNameResolver : IconsNameResolver;
		if( m_itemData != NULL )
		{
			DEBUG_NewUpdateIconErrorInfo();
			return;
		}
		iconsNameResolver = IconsNameResolver.GetIconsNameResolver();
		if( !( iconsNameResolver.IsInDebugMode() ) )
		{
			inkWidgetRef.SetVisible( DEBUG_iconErrorWrapper, false );
			return;
		}
		errorData = m_data.DEBUG_iconErrorInfo;
		inkWidgetRef.SetVisible( DEBUG_iconErrorWrapper, ( errorData != NULL ) || DEBUG_showDebug );
		if( DEBUG_showDebug )
		{
			resultText += " - itemID:\n";
			resultText += TDBID.ToStringDEBUG( m_data.itemTweakID );
			OpenTweakDBRecordInVSCodeIfRequested( m_data.itemTweakID );
			if( m_data.itemData.HasTag( 'Recipe' ) )
			{
				recipeRecord = TweakDBInterface.GetRecipeItemRecord( m_data.itemTweakID );
				if( recipeRecord )
				{
					recipeRecord.CraftableItems( craftableItems );
					if( craftableItems.Size() > 0 )
					{
						resultText += "\n - inner itemID:\n";
						resultText += TDBID.ToStringDEBUG( craftableItems[ 0 ].GetID() );
					}
				}
			}
			inkTextRef.SetText( DEBUG_iconErrorText, resultText );
		}
		else
		{
			if( errorData != NULL )
			{
				resultText += ( ( "   ErrorType: " + EnumValueToString( "inkIconResult", ( ( Int32 )( errorData.errorType ) ) ) ) + "\n\n" );
				resultText += " - itemID:\n";
				resultText += errorData.itemName;
				if( IsStringValid( errorData.innerItemName ) )
				{
					resultText += "\n - inner itemID:\n";
					resultText += errorData.innerItemName;
				}
				if( errorData.isManuallySet )
				{
					resultText += "\n - resolved icon name (manually set):\n";
				}
				else
				{
					resultText += "\n - resolved icon name (auto generated):\n";
				}
				resultText += errorData.resolvedIconName;
				resultText += "\n - error message:\n";
				resultText += errorData.errorMessage;
				inkTextRef.SetText( DEBUG_iconErrorText, resultText );
			}
		}
	}

	private function DEBUG_NewUpdateIconErrorInfo()
	{
		var craftableItems : array< weak< Item_Record > >;
		var recipeRecord : RecipeItem_Record;
		var resultText : String;
		var errorData : DEBUG_IconErrorInfo;
		var iconsNameResolver : IconsNameResolver;
		iconsNameResolver = IconsNameResolver.GetIconsNameResolver();
		if( !( iconsNameResolver.IsInDebugMode() ) )
		{
			inkWidgetRef.SetVisible( DEBUG_iconErrorWrapper, false );
			return;
		}
		errorData = m_itemData.DEBUG_iconErrorInfo;
		inkWidgetRef.SetVisible( DEBUG_iconErrorWrapper, ( errorData != NULL ) || DEBUG_showDebug );
		if( DEBUG_showDebug )
		{
			resultText += " - itemID:\n";
			resultText += TDBID.ToStringDEBUG( m_itemData.GetRealTweakDBID() );
			OpenTweakDBRecordInVSCodeIfRequested( m_itemData.GetRealTweakDBID() );
			if( m_itemData.IsRecipe() )
			{
				recipeRecord = TweakDBInterface.GetRecipeItemRecord( m_itemData.GetRealTweakDBID() );
				if( recipeRecord )
				{
					recipeRecord.CraftableItems( craftableItems );
					if( craftableItems.Size() > 0 )
					{
						resultText += "\n - inner itemID:\n";
						resultText += TDBID.ToStringDEBUG( craftableItems[ 0 ].GetID() );
					}
				}
			}
			inkTextRef.SetText( DEBUG_iconErrorText, resultText );
		}
		else
		{
			if( errorData != NULL )
			{
				resultText += ( ( "   ErrorType: " + EnumValueToString( "inkIconResult", ( ( Int32 )( errorData.errorType ) ) ) ) + "\n\n" );
				resultText += " - itemID:\n";
				resultText += errorData.itemName;
				if( IsStringValid( errorData.innerItemName ) )
				{
					resultText += "\n - inner itemID:\n";
					resultText += errorData.innerItemName;
				}
				if( errorData.isManuallySet )
				{
					resultText += "\n - resolved icon name (manually set):\n";
				}
				else
				{
					resultText += "\n - resolved icon name (auto generated):\n";
				}
				resultText += errorData.resolvedIconName;
				resultText += "\n - error message:\n";
				resultText += errorData.errorMessage;
				inkTextRef.SetText( DEBUG_iconErrorText, resultText );
			}
		}
	}

	public function OnVarModified( groupPath : CName, varName : CName, varType : ConfigVarType, reason : ConfigChangeReason )
	{
		switch( varName )
		{
			case 'BigFont':
				NewUpdateTooltipSize();
			break;
			default:
				break;
		}
	}

	private function NewUpdateTooltipSize()
	{
		var configVar : ConfigVarBool;
		configVar = ( ( ConfigVarBool )( m_settings.GetVar( m_groupPath, 'BigFont' ) ) );
		NewSetTooltipSize( configVar.GetValue() );
	}

	protected virtual function NewSetTooltipSize( value : Bool )
	{
		if( value == true && !( m_inCrafting ) )
		{
			inkWidgetRef.SetSize( m_minWidth, 810.0, 0.0 );
			m_bigFontEnabled = true;
		}
		else
		{
			inkWidgetRef.SetSize( m_minWidth, 710.0, 0.0 );
			m_bigFontEnabled = false;
		}
	}

	private function RegisterUserSettingsListener()
	{
		m_settings = new UserSettings;
		m_settingsListener = new NewItemTooltipSettingsListener;
		m_settingsListener.RegisterController( this );
		m_settingsListener.Register( m_groupPath );
	}

}

class NewItemTooltipModuleController extends inkLogicController
{
	protected editable var m_lineWidget : inkWidgetRef;
	protected var m_displayContext : ItemDisplayContextData;
	protected var m_tooltipDisplayContext : InventoryTooltipDisplayContext;
	protected var m_itemDisplayContext : ItemDisplayContext;

	public virtual function Update( data : MinimalItemTooltipData ) {}

	public virtual function NEW_Update( data : weak< UIInventoryItem > ) {}

	public function SetDisplayContext( itemDisplayContext : ItemDisplayContext, tooltipDisplayContext : InventoryTooltipDisplayContext, displayContext : ItemDisplayContextData )
	{
		m_displayContext = displayContext;
		m_itemDisplayContext = itemDisplayContext;
		m_tooltipDisplayContext = tooltipDisplayContext;
	}

	protected function IsContext( context : InventoryTooltipDisplayContext ) : Bool
	{
		return m_tooltipDisplayContext == context;
	}

	protected function IsContext( data : MinimalItemTooltipData, context : InventoryTooltipDisplayContext ) : Bool
	{
		return data.displayContext == context;
	}

	protected function GetArrowWrapperState( diffValue : Float ) : CName
	{
		if( diffValue < 0.0 )
		{
			return 'Worse';
		}
		else if( diffValue > 0.0 )
		{
			return 'Better';
		}
		return 'Default';
	}

}

class NewItemTooltipModuleSpawnedCallbackData
{
	var moduleName : CName;
}

class NewItemTooltipEquippedModule extends NewItemTooltipModuleController
{
}

class NewItemTooltipRepiceModule extends NewItemTooltipModuleController
{
	private editable var m_itemNameText : inkTextRef;

	public override function Update( data : MinimalItemTooltipData )
	{
		if( IsContext( InventoryTooltipDisplayContext.Crafting ) )
		{
			inkTextRef.SetVisible( m_itemNameText, false );
		}
		else
		{
			UpdateName( data );
		}
	}

	private function UpdateName( data : MinimalItemTooltipData )
	{
		var finalItemName : String;
		inkTextRef.SetVisible( m_itemNameText, true );
		finalItemName = UIItemsHelper.GetTooltipItemName( data.itemTweakID, data.itemData, data.itemName );
		if( data.quantity > 1 )
		{
			finalItemName += ( ( " [" + IntToString( data.quantity ) ) + "]" );
		}
		inkTextRef.SetText( m_itemNameText, finalItemName );
	}

	public override function NEW_Update( data : weak< UIInventoryItem > )
	{
		if( IsContext( InventoryTooltipDisplayContext.Crafting ) )
		{
			inkTextRef.SetVisible( m_itemNameText, false );
		}
		else
		{
			NEW_UpdateName( data.GetName(), data.GetQuantity() );
		}
	}

	private function NEW_UpdateName( itemName : String, quantity : Int32 )
	{
		inkTextRef.SetVisible( m_itemNameText, true );
		if( quantity > 1 )
		{
			itemName += ( ( " [" + IntToString( quantity ) ) + "]" );
		}
		inkTextRef.SetText( m_itemNameText, itemName );
	}

}

class NewItemTooltipHeaderController extends NewItemTooltipModuleController
{
	private editable var m_itemNameText : inkTextRef;
	private editable var m_itemRarityText : inkTextRef;
	private editable var m_itemTypeText : inkTextRef;
	private editable var m_comparisionArrow : inkWidgetRef;
	private editable var m_itemEvolutionIcon : inkImageRef;
	private editable var m_itemPerkIcon : inkImageRef;
	private editable var m_itemWeaponIcon : inkImageRef;
	private editable var m_separatorTop : inkWidgetRef;
	private var m_localizedIconicText : String;

	protected event OnInitialize()
	{
		m_localizedIconicText = GetLocalizedText( UIItemsHelper.QualityToDefaultString( gamedataQuality.Iconic ) );
	}

	public function NEW_UpdateWrapping( bigFontEnabled : Bool )
	{
		if( bigFontEnabled == true )
		{
			inkTextRef.SetWrappingAtPosition( m_itemNameText, 750.0 );
			inkTextRef.SetWrappingAtPosition( m_itemRarityText, 750.0 );
			inkTextRef.SetWrappingAtPosition( m_itemTypeText, 685.0 );
		}
		else
		{
			inkTextRef.SetWrappingAtPosition( m_itemNameText, 650.0 );
			inkTextRef.SetWrappingAtPosition( m_itemRarityText, 650.0 );
			inkTextRef.SetWrappingAtPosition( m_itemTypeText, 585.0 );
		}
	}

	public override function Update( data : MinimalItemTooltipData )
	{
		var itemData : weak< gameItemData >;
		var equipmentArea : gamedataEquipmentArea;
		var itemTweakID : TweakDBID;
		var itemType : gamedataItemType;
		var itemEvolution : gamedataWeaponEvolution;
		var itemTypeText : String;
		var newItemTypeText : String;
		itemData = data.itemData;
		equipmentArea = data.equipmentArea;
		itemTweakID = data.itemTweakID;
		itemType = data.itemType;
		itemEvolution = data.itemEvolution;
		itemTypeText = UIItemsHelper.GetItemTypeKey( itemData, equipmentArea, itemTweakID, itemType, itemEvolution );
		if( data.itemType == gamedataItemType.Wea_Fists )
		{
			newItemTypeText = ( GetLocalizedText( itemTypeText ) + " - " ) + GetLocalizedText( "LocKey#77968" );
			inkTextRef.SetText( m_itemTypeText, newItemTypeText );
			inkTextRef.SetVisible( m_itemTypeText, true );
		}
		else
		{
			inkTextRef.SetText( m_itemTypeText, itemTypeText );
			inkTextRef.SetVisible( m_itemTypeText, true );
		}
		if( data.itemData.HasTag( 'Recipe' ) == true && ( m_tooltipDisplayContext != InventoryTooltipDisplayContext.Crafting && m_tooltipDisplayContext != InventoryTooltipDisplayContext.Upgrading ) )
		{
			inkTextRef.SetVisible( m_itemNameText, false );
			UpdateRarity( data );
			UpdateWeaponEvolution( data );
			UpdatePerkGroup( data );
			UpdateWeaponType( data );
		}
		else if( IsContext( data, InventoryTooltipDisplayContext.Upgrading ) )
		{
			UpdateContentForUpgrading( data );
		}
		else if( IsContext( data, InventoryTooltipDisplayContext.Crafting ) )
		{
			UpdateContentForCrafting( data );
		}
		else
		{
			UpdateName( data );
			UpdateRarity( data );
			UpdateWeaponEvolution( data );
			UpdatePerkGroup( data );
			UpdateWeaponType( data );
			UpdateComparisonArrow( data.qualityF, data.comparisonQualityF, data.isEquipped );
		}
		if( data.isBroken )
		{
			inkTextRef.SetVisible( m_itemRarityText, false );
			inkTextRef.SetVisible( m_itemTypeText, false );
			inkWidgetRef.SetVisible( m_comparisionArrow, false );
			inkImageRef.SetVisible( m_itemEvolutionIcon, false );
			inkImageRef.SetVisible( m_itemPerkIcon, false );
			inkImageRef.SetVisible( m_itemWeaponIcon, false );
			inkWidgetRef.SetVisible( m_separatorTop, false );
		}
	}

	private function UpdateComparisonArrow( qualityF : Float, comparisonQualityF : Float, isEquipped : Bool )
	{
		var isBetter : Bool;
		if( ( ( comparisonQualityF < 0.0 ) || FloatIsEqual( qualityF, comparisonQualityF ) ) || isEquipped )
		{
			inkWidgetRef.SetVisible( m_comparisionArrow, false );
		}
		else
		{
			isBetter = qualityF > comparisonQualityF;
			inkWidgetRef.SetVisible( m_comparisionArrow, true );
			inkWidgetRef.SetState( m_comparisionArrow, ( ( isBetter ) ? ( 'Better' ) : ( 'Default' ) ) );
			inkWidgetRef.SetRotation( m_comparisionArrow, ( ( isBetter ) ? ( 0.0 ) : ( 180.0 ) ) );
			if( inkWidgetRef.GetRotation( m_comparisionArrow ) == 180.0 )
			{
				inkWidgetRef.SetTintColor( m_comparisionArrow, inkTextRef.GetTintColor( m_itemTypeText ) );
			}
		}
		inkWidgetRef.SetVisible( m_comparisionArrow, false );
	}

	private function UpdateContentForUpgrading( data : MinimalItemTooltipData )
	{
		UpdateRarity( data );
		inkTextRef.SetVisible( m_itemNameText, false );
		inkWidgetRef.SetVisible( m_comparisionArrow, false );
		inkImageRef.SetVisible( m_itemEvolutionIcon, false );
		inkImageRef.SetVisible( m_itemPerkIcon, false );
		inkImageRef.SetVisible( m_itemWeaponIcon, false );
		inkTextRef.SetVisible( m_itemTypeText, false );
	}

	private function UpdateContentForCrafting( data : MinimalItemTooltipData )
	{
		var itemTweakID : TweakDBID;
		var itemRecord : Item_Record;
		var ammoCountText : String;
		var fullAmmoText : String;
		itemTweakID = data.itemTweakID;
		itemRecord = TweakDBInterface.GetItemRecord( itemTweakID );
		inkTextRef.SetVisible( m_itemNameText, false );
		inkTextRef.SetVisible( m_itemRarityText, false );
		inkWidgetRef.SetVisible( m_comparisionArrow, false );
		UpdateWeaponEvolution( data );
		UpdatePerkGroup( data );
		UpdateWeaponType( data );
		UpdateSeparator( data );
		if( itemRecord.TagsContains( 'Ammo' ) )
		{
			ammoCountText = ( " [" + data.ammoCount ) + "]";
			fullAmmoText = inkTextRef.GetText( m_itemTypeText );
			fullAmmoText = fullAmmoText + ammoCountText;
			inkTextRef.SetText( m_itemTypeText, fullAmmoText );
		}
	}

	private function UpdateWeaponEvolution( data : MinimalItemTooltipData )
	{
		if( data.itemEvolution != gamedataWeaponEvolution.Invalid )
		{
			inkImageRef.SetTexturePart( m_itemEvolutionIcon, UIItemsHelper.GetWeaponEvolutionTexturePart( data.itemEvolution ) );
			inkImageRef.SetVisible( m_itemEvolutionIcon, true );
		}
		else if( data.itemType == gamedataItemType.Wea_Fists )
		{
			inkImageRef.SetTexturePart( m_itemEvolutionIcon, 'ico_blunt' );
			inkImageRef.SetVisible( m_itemEvolutionIcon, true );
		}
		else
		{
			inkImageRef.SetVisible( m_itemEvolutionIcon, false );
		}
	}

	private function UpdatePerkGroup( data : MinimalItemTooltipData )
	{
		if( data.itemPerkGroup != gamedataPerkWeaponGroupType.Invalid )
		{
			inkImageRef.SetTexturePart( m_itemPerkIcon, UIItemsHelper.GetBasicPerkRelevance( data.itemPerkGroup ) );
			inkImageRef.SetVisible( m_itemPerkIcon, true );
		}
		else
		{
			inkImageRef.SetVisible( m_itemPerkIcon, false );
		}
	}

	private function UpdateWeaponType( data : MinimalItemTooltipData )
	{
		if( data.itemType != gamedataItemType.Invalid )
		{
			inkImageRef.SetTexturePart( m_itemWeaponIcon, UIItemsHelper.GetWeaponTooltipIcon( data.itemType ) );
			inkImageRef.SetVisible( m_itemWeaponIcon, true );
		}
		else
		{
			inkImageRef.SetVisible( m_itemWeaponIcon, false );
		}
	}

	private function UpdateSeparator( data : MinimalItemTooltipData )
	{
		if( inkWidgetRef.IsValid( m_separatorTop ) )
		{
			inkWidgetRef.SetVisible( m_separatorTop, data.displayContext != InventoryTooltipDisplayContext.Crafting );
		}
	}

	private function UpdateName( data : MinimalItemTooltipData )
	{
		var finalItemName : String;
		inkTextRef.SetVisible( m_itemNameText, true );
		finalItemName = UIItemsHelper.GetTooltipItemName( data.itemTweakID, data.itemData, data.itemName );
		if( data.quantity > 1 )
		{
			finalItemName += ( ( " [" + IntToString( data.quantity ) ) + "]" );
		}
		inkTextRef.SetText( m_itemNameText, finalItemName );
	}

	private function UpdateRarity( data : MinimalItemTooltipData )
	{
		var qualityName : CName;
		var rarityLabel, iconicLabel, plusLabel : String;
		if( !( data.hasRarity ) || !( UIItemsHelper.ShouldDisplayTier( data.itemType ) ) )
		{
			inkTextRef.SetVisible( m_itemRarityText, false );
			return;
		}
		inkTextRef.SetVisible( m_itemRarityText, true );
		qualityName = UIItemsHelper.QualityEnumToName( data.quality );
		rarityLabel = GetLocalizedText( UIItemsHelper.QualityToDefaultString( data.quality ) );
		iconicLabel = GetLocalizedText( UIItemsHelper.QualityToDefaultString( gamedataQuality.Iconic ) );
		plusLabel = rarityLabel;
		inkTextRef.SetState( m_itemNameText, qualityName );
		inkTextRef.SetState( m_itemRarityText, qualityName );
		if( data.isPlus >= 2.0 )
		{
			plusLabel += "++";
		}
		else if( data.isPlus >= 1.0 )
		{
			plusLabel += "+";
		}
		if( data.isIconic )
		{
			plusLabel += ( " / " + iconicLabel );
		}
		inkTextRef.SetText( m_itemRarityText, plusLabel );
	}

	public function NEW_Update( data : weak< UIInventoryItem >, comparisonData : weak< UIInventoryItemComparisonManager > )
	{
		var itemData : weak< gameItemData >;
		var equipmentArea : gamedataEquipmentArea;
		var tweakID : TweakDBID;
		var itemType : gamedataItemType;
		var itemEvolution : gamedataWeaponEvolution;
		var itemTypeKey : String;
		var isItemTypeVisible, isBroken : Bool;
		itemData = data.GetRealItemData();
		equipmentArea = data.GetEquipmentArea();
		tweakID = data.GetTweakDBID();
		itemType = data.GetItemType();
		itemEvolution = data.GetWeaponEvolution();
		itemTypeKey = UIItemsHelper.GetItemTypeKey( itemData, equipmentArea, tweakID, itemType, itemEvolution );
		isBroken = data.IsBroken();
		isItemTypeVisible = ( !( data.IsRecipe() ) || data.IsWeapon() ) && !( isBroken );
		inkTextRef.SetVisible( m_itemTypeText, isItemTypeVisible );
		inkTextRef.SetText( m_itemTypeText, itemTypeKey );
		if( IsContext( InventoryTooltipDisplayContext.Crafting ) )
		{
			inkTextRef.SetVisible( m_itemNameText, false );
			inkTextRef.SetVisible( m_itemRarityText, false );
			inkWidgetRef.SetVisible( m_comparisionArrow, false );
			inkImageRef.SetVisible( m_itemEvolutionIcon, true );
			inkImageRef.SetVisible( m_itemPerkIcon, true );
			inkImageRef.SetVisible( m_itemWeaponIcon, true );
		}
		else if( data.IsRecipe() && ( m_tooltipDisplayContext != InventoryTooltipDisplayContext.Crafting && m_tooltipDisplayContext != InventoryTooltipDisplayContext.Upgrading ) )
		{
			inkTextRef.SetVisible( m_itemNameText, false );
			NEW_UpdateRarity( data );
			inkTextRef.SetVisible( m_itemRarityText, true );
			inkWidgetRef.SetVisible( m_comparisionArrow, false );
			inkImageRef.SetTexturePart( m_itemEvolutionIcon, UIItemsHelper.GetWeaponEvolutionTexturePart( data.GetWeaponEvolution() ) );
			inkImageRef.SetVisible( m_itemEvolutionIcon, true );
			inkImageRef.SetTexturePart( m_itemPerkIcon, UIItemsHelper.GetBasicPerkRelevance( data.GetPerkGroup() ) );
			inkImageRef.SetVisible( m_itemPerkIcon, true );
			inkImageRef.SetTexturePart( m_itemWeaponIcon, UIItemsHelper.GetWeaponTooltipIcon( data.GetItemType() ) );
			inkImageRef.SetVisible( m_itemWeaponIcon, true );
		}
		else
		{
			NEW_UpdateName( data.GetName(), data.GetQuantity() );
			if( !( isBroken ) && UIItemsHelper.ShouldDisplayTier( data.GetItemType() ) )
			{
				NEW_UpdateRarity( data );
			}
			else
			{
				inkTextRef.SetVisible( m_itemRarityText, false );
			}
			if( ( !( isBroken ) && data.GetWeaponEvolution() != gamedataWeaponEvolution.Invalid ) && isItemTypeVisible )
			{
				inkImageRef.SetTexturePart( m_itemEvolutionIcon, UIItemsHelper.GetWeaponEvolutionTexturePart( data.GetWeaponEvolution() ) );
				inkImageRef.SetVisible( m_itemEvolutionIcon, true );
			}
			else
			{
				inkImageRef.SetVisible( m_itemEvolutionIcon, false );
			}
			if( !( isBroken ) && data.GetPerkGroup() != gamedataPerkWeaponGroupType.Invalid )
			{
				inkImageRef.SetTexturePart( m_itemPerkIcon, UIItemsHelper.GetBasicPerkRelevance( data.GetPerkGroup() ) );
				inkImageRef.SetVisible( m_itemPerkIcon, true );
			}
			else
			{
				inkImageRef.SetVisible( m_itemPerkIcon, false );
			}
			if( !( isBroken ) && data.GetItemType() != gamedataItemType.Invalid )
			{
				inkImageRef.SetTexturePart( m_itemWeaponIcon, UIItemsHelper.GetWeaponTooltipIcon( data.GetItemType() ) );
				inkImageRef.SetVisible( m_itemWeaponIcon, true );
			}
			else
			{
				inkImageRef.SetVisible( m_itemWeaponIcon, false );
			}
			inkWidgetRef.SetVisible( m_comparisionArrow, false );
			inkWidgetRef.SetVisible( m_separatorTop, !( isBroken ) && !( IsContext( InventoryTooltipDisplayContext.Crafting ) ) );
		}
	}

	private function NEW_UpdateName( itemName : String, quantity : Int32 )
	{
		inkTextRef.SetVisible( m_itemNameText, true );
		if( quantity > 1 )
		{
			itemName += ( ( " [" + IntToString( quantity ) ) + "]" );
		}
		inkTextRef.SetText( m_itemNameText, itemName );
	}

	private function NEW_UpdateRarity( data : weak< UIInventoryItem > )
	{
		var qualityName : CName;
		inkTextRef.SetVisible( m_itemRarityText, true );
		qualityName = UIItemsHelper.QualityEnumToName( data.GetQuality() );
		inkTextRef.SetState( m_itemNameText, qualityName );
		inkTextRef.SetState( m_itemRarityText, qualityName );
		inkTextRef.SetText( m_itemRarityText, data.GetQualityText() );
	}

}

class NewItemTooltipWeaponBarsModule extends NewItemTooltipModuleController
{
	editable var m_wrapper : inkWidgetRef;
	const editable var m_bars : array< inkWidgetRef >;
	const editable var m_diffBars : array< inkWidgetRef >;
	editable var m_betterColorDummyHolder : inkWidgetRef;
	editable var m_worseColorDummyHolder : inkWidgetRef;
	private var m_statsToDisplay : array< WeaponBarType >;
	private var m_disableSeparators : Bool;

	protected event OnInitialize()
	{
		var i, limit : Int32;
		var betterColor, worseColor : HDRColor;
		betterColor = inkWidgetRef.GetTintColor( m_betterColorDummyHolder );
		worseColor = inkWidgetRef.GetTintColor( m_worseColorDummyHolder );
		for( i = 0, limit = m_bars.Size(); i < limit; i += 1 )
		{
			( ( weak< weak< NewItemTooltipStatBarController > > )( inkWidgetRef.GetController( m_bars[ i ] ) ) ).SetupColors( betterColor, worseColor );
		}
	}

	public function UpdateWrapping( bigFontEnabled : Bool, data : MinimalItemTooltipData )
	{
		if( bigFontEnabled )
		{
			inkWidgetRef.SetMargin( m_wrapper, 60.0, 0.0, 0.0, 0.0 );
		}
		else
		{
			inkWidgetRef.SetMargin( m_wrapper, 0.0, 0.0, 0.0, 0.0 );
		}
	}

	public function NEW_UpdateWrapping( bigFontEnabled : Bool )
	{
		if( bigFontEnabled )
		{
			inkWidgetRef.SetMargin( m_wrapper, 60.0, 0.0, 0.0, 0.0 );
		}
		else
		{
			inkWidgetRef.SetMargin( m_wrapper, 0.0, 0.0, 0.0, 0.0 );
		}
	}

	public override function Update( data : MinimalItemTooltipData )
	{
		var statsManager : weak< UIInventoryItemStatsManager >;
		var weaponBars : weak< UIInventoryItemWeaponBars >;
		var itemType : gamedataItemType;
		statsManager = data.GetStatsManager();
		weaponBars = statsManager.GetWeaponBars();
		itemType = data.itemType;
		m_disableSeparators = !( statsManager.IsSeparatorBarsEnabled() );
		if( data.isEquipped )
		{
			CommonUpdate( itemType, weaponBars );
		}
		else
		{
			CommonUpdate( itemType, weaponBars, true );
		}
	}

	public function NEW_Update( data : weak< UIInventoryItem >, comparisonData : weak< UIInventoryItemComparisonManager > )
	{
		m_disableSeparators = !( data.GetStatsManager().IsSeparatorBarsEnabled() );
		if( data.IsEquipped() )
		{
			CommonUpdate( data.GetItemType(), data.GetStatsManager().GetWeaponBars() );
		}
		else
		{
			CommonUpdate( data.GetItemType(), data.GetStatsManager().GetWeaponBars(), true );
		}
	}

	public function CommonUpdate( itemType : gamedataItemType, bars : weak< UIInventoryItemWeaponBars >, optional shouldCompare : Bool )
	{
		var i, limit, statsToDisplaySize : Int32;
		var controller : weak< NewItemTooltipStatBarController >;
		var comparedBars : weak< UIInventoryItemWeaponBars >;
		m_statsToDisplay = UIInventoryItemWeaponBars.GetDisplayedStats( bars.GetType() );
		statsToDisplaySize = m_statsToDisplay.Size();
		if( shouldCompare )
		{
			comparedBars = bars.GetComparedBars();
		}
		for( i = 0, limit = m_bars.Size(); i < limit; i += 1 )
		{
			controller = ( ( weak< weak< NewItemTooltipStatBarController > > )( inkWidgetRef.GetController( m_bars[ i ] ) ) );
			controller.SetSeparatorsVisibility( !( m_disableSeparators ) );
			if( i < statsToDisplaySize )
			{
				inkWidgetRef.SetVisible( m_bars[ i ], true );
				controller.Setup( itemType, bars.Values[ i ], comparedBars.GetComparableBar( bars.Values[ i ].Type ) );
			}
			else
			{
				inkWidgetRef.SetVisible( m_bars[ i ], false );
				controller.ResetPercentage();
			}
		}
	}

}

class NewItemTooltipStatBarController extends inkLogicController
{
	private editable var m_background : inkWidgetRef;
	private editable var m_bar : inkWidgetRef;
	private editable var m_comparisonBar : inkWidgetRef;
	private editable var m_statName : inkTextRef;
	private editable var m_overflow : inkTextRef;
	private editable var m_statValue : inkTextRef;
	private editable var m_comparisonArrow : inkWidgetRef;
	private editable var m_separators : inkWidgetRef;
	private var m_barAnimProxy : inkAnimProxy;
	private var m_diffBarAnimProxy : inkAnimProxy;
	private var m_betterColor : HDRColor;
	private var m_worseColor : HDRColor;
	private var m_width : Float;

	protected event OnInitialize()
	{
		m_width = inkWidgetRef.GetWidth( m_background );
	}

	public function SetupColors( betterColor : HDRColor, worseColor : HDRColor )
	{
		m_betterColor = betterColor;
		m_worseColor = worseColor;
	}

	public function ResetPercentage()
	{
		inkWidgetRef.SetWidth( m_bar, 0.0 );
		inkWidgetRef.SetWidth( m_comparisonBar, 0.0 );
	}

	public function SetSeparatorsVisibility( visible : Bool )
	{
		inkWidgetRef.SetVisible( m_separators, visible );
	}

	public function Setup( itemType : gamedataItemType, bar : weak< UIInventoryItemWeaponBar >, comparedBar : weak< UIInventoryItemWeaponBar > )
	{
		var percentage, comparedPercentage, diff : Float;
		var overflow, isBetter : Bool;
		var numericValue : Float;
		var numericValueString : String;
		numericValue = GetNumericValue( itemType, bar.Type, bar.Value, bar.MaxValue );
		if( numericValue < 10.0 )
		{
			numericValueString = FloatToStringPrec( numericValue, 1 );
			if( StrLen( numericValueString ) == 1 )
			{
				numericValueString += ".0";
			}
		}
		else
		{
			numericValueString = IntToString( RoundFEx( numericValue ) );
		}
		inkTextRef.SetText( m_statName, BarTypeToName( bar.Type ) );
		inkTextRef.SetText( m_statValue, numericValueString );
		if( ( comparedBar != NULL ) && comparedBar.IsValueSet() )
		{
			diff = bar.Percentage - comparedBar.Percentage;
			if( ( FloatIsEqual( diff, 0.0 ) && ( bar.Percentage > 1.0 ) ) && ( comparedBar.Percentage > 1.0 ) )
			{
				diff = SgnF( bar.Value - comparedBar.Value );
			}
			if( FloatIsEqual( diff, 0.0 ) )
			{
				inkWidgetRef.SetVisible( m_comparisonArrow, false );
			}
			else
			{
				isBetter = diff > 0.0;
				if( UIInventoryItemWeaponBars.IsBarReversed( bar.Type ) )
				{
					isBetter != isBetter;
				}
				inkWidgetRef.SetState( m_comparisonArrow, ( ( isBetter ) ? ( 'Better' ) : ( 'Worse' ) ) );
				inkWidgetRef.SetRotation( m_comparisonArrow, ( ( isBetter ) ? ( 180.0 ) : ( 0.0 ) ) );
				inkWidgetRef.SetVisible( m_comparisonArrow, true );
			}
		}
		else
		{
			inkWidgetRef.SetVisible( m_comparisonArrow, false );
		}
		percentage = bar.Percentage;
		if( ( comparedBar != NULL ) && comparedBar.IsValueSet() )
		{
			comparedPercentage = comparedBar.Percentage;
			if( bar.Percentage < comparedBar.Percentage )
			{
				comparedPercentage = comparedPercentage - percentage;
			}
			else
			{
				percentage = comparedBar.Percentage;
				comparedPercentage = bar.Percentage - comparedBar.Percentage;
			}
			if( ( percentage > 1.0 ) && ( comparedBar.Percentage > 0.0 ) )
			{
				percentage = 1.0;
				comparedPercentage = 0.0;
				overflow = true;
			}
			else if( ( comparedPercentage + percentage ) > 1.0 )
			{
				comparedPercentage = 1.0 - percentage;
				overflow = true;
			}
		}
		else
		{
			comparedPercentage = 0.0;
		}
		if( percentage > 1.0 )
		{
			overflow = true;
			percentage = 1.0;
		}
		inkTextRef.SetVisible( m_overflow, overflow );
		AnimateBars( bar.Type, percentage, comparedPercentage, isBetter );
	}

	private function GetNumericValue( itemType : gamedataItemType, barType : WeaponBarType, value : Float, maxValue : Float ) : Float
	{
		if( barType == WeaponBarType.Handling )
		{
			value = value * ( 10.0 / 0.31 );
		}
		return value;
	}

	private function BarTypeToName( barType : WeaponBarType ) : String
	{
		switch( barType )
		{
			case WeaponBarType.AttackSpeed:
				return "LocKey#36318";
			case WeaponBarType.DamagePerHit:
				return "LocKey#36314";
			case WeaponBarType.ReloadSpeed:
				return "LocKey#87960";
			case WeaponBarType.Range:
				return "LocKey#87961";
			case WeaponBarType.Handling:
				return "LocKey#87962";
			case WeaponBarType.Stamina:
				return "LocKey#87963";
			case WeaponBarType.MeleeAttackSpeed:
				return "LocKey#36318";
			case WeaponBarType.MeleeDamagePerHit:
				return "LocKey#87959";
			case WeaponBarType.MeleeStamina:
				return "LocKey#87963";
			case WeaponBarType.ThrowableEffectiveRange:
				return "LocKey#87961";
			case WeaponBarType.ThrowableReturnTime:
				return "LocKey#94329";
			case WeaponBarType.CyberwareAttackSpeed:
				return "LocKey#36318";
			case WeaponBarType.CyberwareDamagePerHit:
				return "LocKey#87959";
			case WeaponBarType.Healing:
				return "LocKey#96015";
			case WeaponBarType.HealingOverTime:
				return "LocKey#96016";
		}
		return "";
	}

	private function AnimateBars( barType : WeaponBarType, percentage : Float, comparedPercentage : Float, isBetter : Bool )
	{
		var startValue, startDiff : Float;
		var barHeight : Float;
		var barAnimDef, diffBarAnimDef : inkAnimDef;
		var barSizeInterpolator, diffBarSizeInterpolator : inkAnimSize;
		var diffBarColorInterpolator : inkAnimColor;
		startValue = inkWidgetRef.GetWidth( m_bar );
		startDiff = inkWidgetRef.GetWidth( m_comparisonBar );
		barHeight = inkWidgetRef.GetHeight( m_bar );
		if( m_barAnimProxy )
		{
			m_barAnimProxy.Stop();
		}
		if( m_diffBarAnimProxy )
		{
			m_diffBarAnimProxy.Stop();
		}
		barAnimDef = new inkAnimDef;
		barSizeInterpolator = new inkAnimSize;
		barSizeInterpolator.SetStartSize( Vector2( startValue, barHeight ) );
		barSizeInterpolator.SetEndSize( Vector2( percentage * m_width, barHeight ) );
		barSizeInterpolator.SetMode( inkanimInterpolationMode.EasyOut );
		barSizeInterpolator.SetType( inkanimInterpolationType.Quadratic );
		barSizeInterpolator.SetDirection( inkanimInterpolationDirection.FromTo );
		barSizeInterpolator.SetDuration( 0.44999999 );
		barAnimDef.AddInterpolator( barSizeInterpolator );
		inkWidgetRef.PlayAnimation( m_bar, barAnimDef );
		diffBarAnimDef = new inkAnimDef;
		diffBarSizeInterpolator = new inkAnimSize;
		diffBarSizeInterpolator.SetStartSize( Vector2( startDiff, barHeight ) );
		diffBarSizeInterpolator.SetEndSize( Vector2( comparedPercentage * m_width, barHeight ) );
		diffBarSizeInterpolator.SetMode( inkanimInterpolationMode.EasyOut );
		diffBarSizeInterpolator.SetType( inkanimInterpolationType.Quadratic );
		diffBarSizeInterpolator.SetDirection( inkanimInterpolationDirection.FromTo );
		diffBarSizeInterpolator.SetDuration( 0.44999999 );
		diffBarAnimDef.AddInterpolator( diffBarSizeInterpolator );
		diffBarColorInterpolator = new inkAnimColor;
		diffBarColorInterpolator.SetStartColor( inkWidgetRef.GetTintColor( m_comparisonBar ) );
		diffBarColorInterpolator.SetEndColor( ( ( isBetter ) ? ( m_betterColor ) : ( m_worseColor ) ) );
		diffBarColorInterpolator.SetMode( inkanimInterpolationMode.EasyOut );
		diffBarColorInterpolator.SetType( inkanimInterpolationType.Quadratic );
		diffBarColorInterpolator.SetDirection( inkanimInterpolationDirection.FromTo );
		diffBarColorInterpolator.SetDuration( 0.44999999 );
		diffBarAnimDef.AddInterpolator( diffBarColorInterpolator );
		inkWidgetRef.PlayAnimation( m_comparisonBar, diffBarAnimDef );
	}

}

class NewItemTooltipRequirementsModule extends NewItemTooltipModuleController
{
	private editable var m_smartlinkGunWrapper : inkWidgetRef;
	private editable var m_line : inkWidgetRef;

	public override function Update( data : MinimalItemTooltipData )
	{
		inkWidgetRef.SetVisible( m_smartlinkGunWrapper, false );
		inkWidgetRef.SetVisible( m_line, false );
		if( data.requirements.isSmartlinkRequirementNotMet )
		{
			inkWidgetRef.SetVisible( m_smartlinkGunWrapper, true );
			inkWidgetRef.SetVisible( m_line, true );
		}
	}

	public function NEW_Update( data : weak< UIInventoryItem >, player : weak< PlayerPuppet > )
	{
		var requiremenetsManager : weak< UIInventoryItemRequirementsManager >;
		inkWidgetRef.SetVisible( m_smartlinkGunWrapper, false );
		inkWidgetRef.SetVisible( m_line, false );
		requiremenetsManager = data.GetRequirementsManager( ( ( weak< weak< GameObject > > )( player ) ) );
		if( !( requiremenetsManager.IsSmartlinkRequirementMet() ) )
		{
			inkWidgetRef.SetVisible( m_smartlinkGunWrapper, true );
			inkWidgetRef.SetVisible( m_line, true );
		}
	}

}

class NewItemTooltipDetailsStatsModule extends NewItemTooltipModuleController
{
	private editable var m_statsContainer : inkCompoundRef;
	private editable var m_isCrafting : Bool;

	public override function Update( data : MinimalItemTooltipData )
	{
		var i, limit : Int32;
		var widget : weak< inkWidget >;
		var controller : ItemTooltipStatController;
		var statsManager : weak< UIInventoryItemStatsManager >;
		statsManager = data.GetStatsManager();
		inkCompoundRef.RemoveAllChildren( m_statsContainer );
		for( i = 0, limit = statsManager.SizeTooltipStats(); i < limit; i += 1 )
		{
			widget = SpawnFromLocal( inkCompoundRef.Get( m_statsContainer ), 'itemDetailsStat' );
			controller = ( ( ItemTooltipStatController )( widget.GetController() ) );
			controller.GetContext( m_isCrafting );
			controller.SetData( statsManager.GetTooltipStat( i ) );
		}
	}

	public override function NEW_Update( data : weak< UIInventoryItem > )
	{
		var i, limit : Int32;
		var widget : weak< inkWidget >;
		var controller : ItemTooltipStatController;
		var statsManager : weak< UIInventoryItemStatsManager >;
		inkCompoundRef.RemoveAllChildren( m_statsContainer );
		statsManager = data.GetStatsManager();
		for( i = 0, limit = statsManager.SizeTooltipStats(); i < limit; i += 1 )
		{
			widget = SpawnFromLocal( inkCompoundRef.Get( m_statsContainer ), 'itemDetailsStat' );
			controller = ( ( ItemTooltipStatController )( widget.GetController() ) );
			controller.GetContext( m_isCrafting );
			controller.SetData( statsManager.GetTooltipStat( i ) );
		}
	}

	public function GetContext( isCrafting : Bool )
	{
		m_isCrafting = isCrafting;
	}

}

class NewItemTooltipDetailsModule extends NewItemTooltipModuleController
{
	private editable var m_statsLine : inkWidgetRef;
	private editable var m_statsWrapper : inkWidgetRef;
	private editable var m_statsContainer : inkCompoundRef;
	private editable var m_dedicatedModsLine : inkWidgetRef;
	private editable var m_dedicatedModsWrapper : inkWidgetRef;
	private editable var m_dedicatedModsText : inkTextRef;
	private editable var m_modsLine : inkWidgetRef;
	private editable var m_modsWrapper : inkWidgetRef;
	private editable var m_modsContainer : inkCompoundRef;
	private editable var m_modifierPowerLine : inkWidgetRef;
	private editable var m_modifierPowerLabel : inkTextRef;
	private editable var m_modifierPowerWrapper : inkCompoundRef;
	private editable var m_isCrafting : Bool;

	public function Update( data : MinimalItemTooltipData, hasDedicatedMods : Bool, hasMods : Bool )
	{
		var abilities : array< InventoryItemAbility >;
		if( hasDedicatedMods )
		{
			if( data.dedicatedMods.Size() > 0 )
			{
				abilities = data.dedicatedMods[ 0 ].abilities;
			}
		}
		if( abilities.Size() > 0 )
		{
			inkWidgetRef.SetVisible( m_dedicatedModsLine, true );
			inkWidgetRef.SetVisible( m_dedicatedModsWrapper, true );
			inkTextRef.SetText( m_dedicatedModsText, abilities[ 0 ].Description );
			if( abilities[ 0 ].LocalizationDataPackage.GetParamsCount() > 0 )
			{
				inkTextRef.SetTextParameters( m_dedicatedModsText, abilities[ 0 ].LocalizationDataPackage.GetTextParams() );
			}
		}
		else
		{
			inkWidgetRef.SetVisible( m_dedicatedModsLine, false );
			inkWidgetRef.SetVisible( m_dedicatedModsWrapper, false );
		}
		if( hasMods )
		{
			inkWidgetRef.SetVisible( m_modsLine, true );
			inkWidgetRef.SetVisible( m_modsWrapper, true );
			UpdateMods( data );
		}
		else
		{
			inkWidgetRef.SetVisible( m_modsLine, false );
			inkWidgetRef.SetVisible( m_modsWrapper, false );
		}
	}

	public function NEW_UpdateWrapping( bigFontEnabled : Bool )
	{
		if( bigFontEnabled == true )
		{
			inkTextRef.SetWrappingAtPosition( m_dedicatedModsText, 750.0 );
		}
		else
		{
			inkTextRef.SetWrappingAtPosition( m_dedicatedModsText, 650.0 );
		}
	}

	private function UpdateMods( data : MinimalItemTooltipData )
	{
		var i, modsSize : Int32;
		var controller : NewItemTooltipAttachmentGroupController;
		modsSize = data.mods.Size();
		while( inkCompoundRef.GetNumChildren( m_modsContainer ) > modsSize )
		{
			inkCompoundRef.RemoveChildByIndex( m_modsContainer, 0 );
		}
		while( inkCompoundRef.GetNumChildren( m_modsContainer ) < modsSize )
		{
			SpawnFromLocal( inkCompoundRef.Get( m_modsContainer ), 'itemTooltipMod' );
		}
		for( i = 0; i < modsSize; i += 1 )
		{
			controller = ( ( NewItemTooltipAttachmentGroupController )( inkCompoundRef.GetWidgetByIndex( m_modsContainer, i ).GetController() ) );
			controller.GetContext( m_isCrafting );
			controller.SetData( data.mods[ i ] );
		}
	}

	public function NEW_Update( data : weak< UIInventoryItem >, m_comparisonData : weak< UIInventoryItemComparisonManager >, hasDedicatedMods : Bool, hasMods : Bool )
	{
		var modsManager : weak< UIInventoryItemModsManager >;
		var abilities : array< InventoryItemAbility >;
		modsManager = data.GetModsManager();
		if( hasDedicatedMods )
		{
			if( modsManager.GetDedicatedMod() != NULL )
			{
				abilities = modsManager.GetDedicatedMod().Abilities;
			}
		}
		if( abilities.Size() > 0 )
		{
			inkWidgetRef.SetVisible( m_dedicatedModsLine, true );
			inkWidgetRef.SetVisible( m_dedicatedModsWrapper, true );
			inkTextRef.SetText( m_dedicatedModsText, abilities[ 0 ].Description );
			if( abilities[ 0 ].LocalizationDataPackage.GetParamsCount() > 0 )
			{
				inkTextRef.SetTextParameters( m_dedicatedModsText, abilities[ 0 ].LocalizationDataPackage.GetTextParams() );
			}
		}
		else
		{
			inkWidgetRef.SetVisible( m_dedicatedModsLine, false );
			inkWidgetRef.SetVisible( m_dedicatedModsWrapper, false );
		}
		if( hasMods )
		{
			inkWidgetRef.SetVisible( m_modsLine, true );
			inkWidgetRef.SetVisible( m_modsWrapper, true );
			NEW_UpdateMods( modsManager );
		}
		else
		{
			inkWidgetRef.SetVisible( m_modsLine, false );
			inkWidgetRef.SetVisible( m_modsWrapper, false );
		}
	}

	private function NEW_UpdateMods( modsManager : weak< UIInventoryItemModsManager > )
	{
		var i, modsSize : Int32;
		var controller : NewItemTooltipAttachmentGroupController;
		modsSize = modsManager.GetModsSize();
		while( inkCompoundRef.GetNumChildren( m_modsContainer ) > modsSize )
		{
			inkCompoundRef.RemoveChildByIndex( m_modsContainer, 0 );
		}
		while( inkCompoundRef.GetNumChildren( m_modsContainer ) < modsSize )
		{
			SpawnFromLocal( inkCompoundRef.Get( m_modsContainer ), 'itemTooltipMod' );
		}
		for( i = 0; i < modsSize; i += 1 )
		{
			controller = ( ( NewItemTooltipAttachmentGroupController )( inkCompoundRef.GetWidgetByIndex( m_modsContainer, i ).GetController() ) );
			controller.GetContext( m_isCrafting );
			controller.SetData( modsManager.GetMod( i ) );
		}
	}

	public function GetContext( isCrafting : Bool )
	{
		m_isCrafting = isCrafting;
	}

}

class NewItemTooltipBottomModule extends NewItemTooltipModuleController
{
	private editable var m_weightWrapper : inkWidgetRef;
	private editable var m_priceWrapper : inkWidgetRef;
	private editable var m_ammoWrapper : inkWidgetRef;
	private editable var m_weightText : inkTextRef;
	private editable var m_priceText : inkTextRef;
	private editable var m_ammoText : inkTextRef;
	private editable var m_ammoIcon : inkImageRef;

	public override function Update( data : MinimalItemTooltipData )
	{
		var isSellable : Bool;
		isSellable = UIInventoryItemsManager.IsSellableStatic( data.itemData );
		inkTextRef.SetText( m_weightText, FloatToStringPrec( data.weight, 1 ) );
		if( !( data.itemData.HasTag( WeaponObject.GetMeleeWeaponTag() ) ) )
		{
			inkWidgetRef.SetVisible( m_ammoWrapper, true );
			inkTextRef.SetText( m_ammoText, IntToString( data.ammoCount ) );
			UpdateAmmoIcon( data.itemData );
		}
		else
		{
			inkWidgetRef.SetVisible( m_ammoWrapper, false );
		}
		if( !( ShouldDisplayPrice( data.displayContext, isSellable, data.itemData, data.itemType, data.lootItemType ) ) )
		{
			inkWidgetRef.SetVisible( m_priceWrapper, false );
			return;
		}
		inkTextRef.SetText( m_priceText, IntToString( RoundF( data.price ) * data.itemData.GetQuantity() ) );
		inkWidgetRef.SetVisible( m_priceWrapper, true );
	}

	public function NEW_Update( data : weak< UIInventoryItem >, player : weak< PlayerPuppet >, m_overridePrice : Int32 )
	{
		inkTextRef.SetText( m_weightText, FloatToStringPrec( data.GetWeight(), 1 ) );
		if( data.IsWeapon() && data.GetWeaponType() == WeaponType.Ranged )
		{
			inkWidgetRef.SetVisible( m_ammoWrapper, true );
			inkTextRef.SetText( m_ammoText, IntToString( data.GetAmmo() ) );
			UpdateAmmoIcon( data.GetItemData() );
		}
		else
		{
			inkWidgetRef.SetVisible( m_ammoWrapper, false );
		}
		if( !( ShouldDisplayPrice( m_tooltipDisplayContext, data.IsSellable(), data.GetItemData(), data.GetItemType() ) ) )
		{
			inkWidgetRef.SetVisible( m_priceWrapper, false );
			return;
		}
		if( m_overridePrice >= 0 )
		{
			inkTextRef.SetText( m_priceText, IntToString( m_overridePrice ) );
		}
		else
		{
			if( m_itemDisplayContext == ItemDisplayContext.Vendor )
			{
				inkTextRef.SetText( m_priceText, IntToString( RoundF( data.GetBuyPrice() ) * data.GetQuantity() ) );
			}
			else
			{
				inkTextRef.SetText( m_priceText, IntToString( RoundF( data.GetSellPrice() ) * data.GetQuantity() ) );
			}
		}
		inkWidgetRef.SetVisible( m_priceWrapper, true );
	}

	private function ShouldDisplayPrice( displayContext : InventoryTooltipDisplayContext, isSellable : Bool, itemData : gameItemData, itemType : gamedataItemType, optional lootItemType : LootItemType ) : Bool
	{
		if( displayContext != InventoryTooltipDisplayContext.Vendor )
		{
			if( ( ( ( ( !( isSellable ) || itemType == gamedataItemType.Con_Ammo ) || itemType == gamedataItemType.Wea_Fists ) || itemData.HasTag( 'Shard' ) ) || itemData.HasTag( 'Recipe' ) ) || lootItemType == LootItemType.Quest )
			{
				return false;
			}
		}
		return true;
	}

	private function UpdateAmmoIcon( itemData : weak< gameItemData > )
	{
		var type : gamedataItemType;
		var icon : CName;
		if( itemData )
		{
			type = itemData.GetItemType();
			icon = UIItemsHelper.GetAmmoIconByType( type );
			inkImageRef.SetTexturePart( m_ammoIcon, icon );
		}
	}

}

class NewItemTooltipDescriptionModule extends NewItemTooltipModuleController
{
	private editable var m_descriptionText : inkTextRef;
	private var m_defaultMargin : inkMargin;

	protected event OnInitialize()
	{
		m_defaultMargin = inkTextRef.GetMargin( m_descriptionText );
	}

	public function UpdateWrapping( bigFontEnabled : Bool )
	{
		if( bigFontEnabled == true )
		{
			inkTextRef.SetWrappingAtPosition( m_descriptionText, 750.0 );
		}
		else
		{
			inkTextRef.SetWrappingAtPosition( m_descriptionText, 650.0 );
		}
	}

	public override function Update( data : MinimalItemTooltipData )
	{
		inkTextRef.SetText( m_descriptionText, data.gameplayDescription );
	}

	public override function NEW_Update( data : weak< UIInventoryItem > )
	{
		var description : String;
		var isBottomHidden : Bool;
		var margin : inkMargin;
		description = data.GetGameplayDescription();
		inkTextRef.SetText( m_descriptionText, description );
		isBottomHidden = data.GetItemType() == gamedataItemType.Wea_HeavyMachineGun || !( data.IsWeapon() );
		margin = m_defaultMargin;
		if( isBottomHidden )
		{
			margin.bottom = 16.0;
		}
		inkTextRef.SetMargin( m_descriptionText, margin );
	}

}

class NewItemTooltipBrokenModule extends NewItemTooltipModuleController
{
	private editable var m_descriptionText : inkTextRef;

	protected event OnInitialize()
	{
		inkTextRef.SetLocalizedTextScript( m_descriptionText, "LocKey#95195" );
	}

	public function NEW_UpdateWrapping( bigFontEnabled : Bool )
	{
		if( bigFontEnabled == true )
		{
			inkTextRef.SetWrappingAtPosition( m_descriptionText, 750.0 );
		}
		else
		{
			inkTextRef.SetWrappingAtPosition( m_descriptionText, 650.0 );
		}
	}

}

class NewItemTooltipSettingsListener extends ConfigVarListener
{
	private var m_ctrl : weak< NewItemTooltipCommonController >;

	public function RegisterController( ctrl : NewItemTooltipCommonController )
	{
		m_ctrl = ctrl;
	}

	public export override function OnVarModified( groupPath : CName, varName : CName, varType : ConfigVarType, reason : ConfigChangeReason )
	{
		m_ctrl.OnVarModified( groupPath, varName, varType, reason );
	}

}

