class FullscreenVendorGameController extends gameuiMenuGameController
{
	private editable var m_TooltipsManagerRef : inkWidgetRef;
	private editable var m_buttonHintsManagerRef : inkWidgetRef;
	private editable var m_playerFiltersContainer : inkWidgetRef;
	private editable var m_vendorFiltersContainer : inkWidgetRef;
	private editable var m_inventoryGridList : inkVirtualCompoundRef;
	private editable var m_vendorSpecialOffersInventoryGridList : inkCompoundRef;
	private editable var m_vendorInventoryGridList : inkVirtualCompoundRef;
	private editable var m_playerInventoryGridScroll : inkWidgetRef;
	private editable var m_vendorInventoryGridScroll : inkWidgetRef;
	private editable var m_notificationRoot : inkWidgetRef;
	private editable var m_emptyStock : inkWidgetRef;
	private editable var m_buyWrapper : inkWidgetRef;
	private editable var m_vendorMoney : inkTextRef;
	private editable var m_vendorName : inkTextRef;
	private editable var m_playerMoney : inkTextRef;
	private editable var m_quantityPicker : inkWidgetRef;
	private editable var m_playerSortingButton : inkWidgetRef;
	private editable var m_vendorSortingButton : inkWidgetRef;
	private editable var m_sortingDropdown : inkWidgetRef;
	private editable var m_playerBalance : inkWidgetRef;
	private editable var m_vendorBalance : inkWidgetRef;
	private var m_TooltipsManager : weak< gameuiTooltipsManager >;
	private var m_buttonHintsController : weak< ButtonHints >;
	private var m_VendorDataManager : VendorDataManager;
	private var m_player : weak< PlayerPuppet >;
	private var m_itemTypeSorting : array< gamedataItemType >;
	private var m_InventoryManager : InventoryDataManagerV2;
	private var m_uiInventorySystem : weak< UIInventoryScriptableSystem >;
	private var m_menuEventDispatcher : weak< inkMenuEventDispatcher >;
	private var m_playerInventoryitemControllers : array< weak< InventoryItemDisplayController > >;
	private var m_vendorInventoryitemControllers : array< weak< InventoryItemDisplayController > >;
	private var m_vendorSpecialOfferInventoryitemControllers : array< weak< InventoryItemDisplayController > >;
	private var m_playerDataSource : ScriptableDataSource;
	private var m_virtualPlayerListController : weak< inkVirtualGridController >;
	private var m_vendorDataSource : ScriptableDataSource;
	private var m_virtualVendorListController : weak< inkVirtualGridController >;
	private var m_playerItemsDataView : VendorDataView;
	private var m_vendorItemsDataView : VendorDataView;
	private var m_itemsClassifier : ItemDisplayTemplateClassifier;
	private var m_totalBuyCost : Float;
	private var m_totalSellCost : Float;
	private var m_root : weak< inkWidget >;
	private var m_vendorUserData : VendorUserData;
	private var m_storageUserData : StorageUserData;
	private var m_comparisonResolver : InventoryItemPreferredComparisonResolver;
	private var m_sellJunkPopupToken : inkGameNotificationToken;
	private var m_quantityPickerPopupToken : inkGameNotificationToken;
	private var m_confirmationPopupToken : inkGameNotificationToken;
	private var m_itemPreviewPopupToken : inkGameNotificationToken;
	private var m_VendorBlackboard : weak< IBlackboard >;
	private var m_VendorBlackboardDef : UI_VendorDef;
	private var m_VendorUpdatedCallbackID : CallbackHandle;
	private var m_craftingBlackboard : weak< IBlackboard >;
	private var m_craftingBlackboardDef : UI_CraftingDef;
	private var m_craftingCallbackID : CallbackHandle;
	private var m_InventoryBlackboard : weak< IBlackboard >;
	private var m_InventoryCallback : UI_InventoryDef;
	private var m_InventoryAddedBBID : CallbackHandle;
	private var m_InventoryRemovedBBID : CallbackHandle;
	private var m_playerFilterManager : ItemCategoryFliterManager;
	private var m_vendorFilterManager : ItemCategoryFliterManager;
	private var m_lastPlayerFilter : ItemFilterCategory;
	private var m_lastVendorFilter : ItemFilterCategory;
	private var m_uiScriptableSystem : weak< UIScriptableSystem >;
	private var m_uiSystem : UISystem;
	private var m_storageDef : StorageBlackboardDef;
	private var m_storageBlackboard : weak< IBlackboard >;
	private var m_itemDropQueue : array< ItemModParams >;
	private var m_isActivePanel : Bool;
	private var m_lastItemHoverOverEvent : ItemDisplayHoverOverEvent;
	private var m_isComparisionDisabled : Bool;
	private var m_lastRequestId : Int32;
	private var sellQueue : array< VenodrRequestQueueEntry >;
	private var buyQueue : array< VenodrRequestQueueEntry >;
	private var m_boughtQuestItems : array< gameItemData >;
	private var m_vendorSoldItems : SoldItemsCache;
	private var m_vendorUIInventoryItems : array< UIInventoryItem >;
	private var m_playerItemDisplayContext : ItemDisplayContextData;
	private var m_vendorItemDisplayContext : ItemDisplayContextData;
	private var m_transactionPending : Bool;
	private var m_screenDisplayContext : ScreenDisplayContext;
	private var m_globalSellInputPending : Bool;
	private var m_isPopupPending : Bool;
	private var m_cursorData : MenuCursorUserData;
	private var m_pressedItemDisplay : weak< InventoryItemDisplayController >;

	protected event OnInitialize()
	{
		SetTimeDilatation( true );
		RegisterToGlobalInputCallback( 'OnPostOnPress', this, 'OnHandleGlobalPress' );
		RegisterToGlobalInputCallback( 'OnPostOnRelease', this, 'OnHandleGlobalRelease' );
	}

	protected event OnSetUserData( userData : IScriptable )
	{
		var vendorPanelData : VendorPanelData;
		var vendorData : VendorData;
		var vendorName : String;
		var storageUserData : StorageUserData;
		m_storageDef = GetAllBlackboardDefs().StorageBlackboard;
		m_storageBlackboard = GetBlackboardSystem().Get( m_storageDef );
		storageUserData = ( ( StorageUserData )( m_storageBlackboard.GetVariant( m_storageDef.StorageData ) ) );
		if( ( userData == NULL ) && ( storageUserData == NULL ) )
		{
			return false;
		}
		inkWidgetRef.SetVisible( m_quantityPicker, false );
		m_vendorUserData = ( ( VendorUserData )( userData ) );
		m_storageUserData = storageUserData;
		if( m_vendorUserData != NULL )
		{
			m_storageUserData = NULL;
		}
		if( m_vendorUserData || m_storageUserData )
		{
			vendorPanelData = m_vendorUserData.vendorData;
			vendorData = vendorPanelData.data;
			m_VendorDataManager = new VendorDataManager;
			if( m_vendorUserData )
			{
				m_VendorDataManager.Initialize( GetPlayerControlledObject(), vendorData.entityID );
				vendorName = m_VendorDataManager.GetVendorName();
				if( !( IsStringValid( vendorName ) ) )
				{
					vendorName = "MISSING VENDOR NAME";
				}
				inkTextRef.SetText( m_vendorName, vendorName );
			}
			else if( m_storageUserData )
			{
				m_VendorDataManager.Initialize( GetPlayerControlledObject(), storageUserData.storageObject.GetEntityID() );
				inkWidgetRef.SetVisible( m_playerBalance, false );
				inkWidgetRef.SetVisible( m_vendorBalance, false );
				inkTextRef.SetText( m_vendorName, "Gameplay-Scanning-Devices-GameplayRoles-Storage" );
			}
			m_lastPlayerFilter = ItemFilterCategory.Invalid;
			m_lastVendorFilter = ItemFilterCategory.AllItems;
			Init();
			UpdateVendorMoney();
			UpdatePlayerMoney();
			m_vendorItemsDataView.DisableSorting();
			PopulateVendorInventory();
			ShowHideVendorStock();
			m_playerItemsDataView.DisableSorting();
			PopulatePlayerInventory();
			SetupDropdown();
			PlayLibraryAnimation( 'vendor_intro' );
		}
	}

	protected event OnUninitialize()
	{
		SetTimeDilatation( false );
		PlaySound( 'GameMenu', 'OnClose' );
		m_InventoryManager.ClearInventoryItemDataCache();
		m_InventoryManager.UnInitialize();
		m_uiInventorySystem.FlushFullscreenCache();
		RemoveBB();
		UnregisterFromGlobalInputCallback( 'OnPostOnPress', this, 'OnHandleGlobalPress' );
		UnregisterFromGlobalInputCallback( 'OnPostOnRelease', this, 'OnHandleGlobalRelease' );
		m_menuEventDispatcher.UnregisterFromEvent( 'OnBack', this, 'OnBack' );
		m_menuEventDispatcher.UnregisterFromEvent( 'OnCloseMenu', this, 'OnCloseMenu' );
		m_menuEventDispatcher.UnregisterFromEvent( 'OnBeforeLeaveScenario', this, 'OnBeforeLeaveScenario' );
		m_menuEventDispatcher.UnregisterFromEvent( 'OnSetScreenDisplayContext', this, 'OnSetScreenDisplayContext' );
		GameInstance.GetTelemetrySystem( m_player.GetGame() ).LogVendorMenuState( m_VendorDataManager.GetVendorID(), false );
		ReleaseVirtualLists();
	}

	protected event OnSetScreenDisplayContext( userData : IScriptable )
	{
		var displayContext : ScreenDisplayContextData;
		displayContext = ( ( ScreenDisplayContextData )( userData ) );
		if( displayContext )
		{
			m_screenDisplayContext = displayContext.Context;
		}
	}

	protected event OnBeforeLeaveScenario( userData : IScriptable )
	{
		if( m_screenDisplayContext == ScreenDisplayContext.Vendor || m_screenDisplayContext == ScreenDisplayContext.Storage )
		{
			MenuUIUtils.RequestAutoSave( m_player, 1.0 );
		}
	}

	protected event OnCloseMenu( userData : IScriptable )
	{
		ReleaseVirtualLists();
	}

	private function InitializeVirtualLists()
	{
		m_itemsClassifier = new ItemDisplayTemplateClassifier;
		m_playerItemsDataView = new VendorDataView;
		m_playerDataSource = new ScriptableDataSource;
		m_playerItemsDataView.BindUIScriptableSystem( m_uiScriptableSystem );
		m_playerItemsDataView.SetSource( m_playerDataSource );
		m_playerItemsDataView.EnableSorting();
		m_playerItemsDataView.SetOpenTime( m_VendorDataManager.GetOpenTime() );
		m_virtualPlayerListController = ( ( inkVirtualGridController )( inkVirtualCompoundRef.GetControllerByType( m_inventoryGridList, 'inkVirtualGridController' ) ) );
		m_virtualPlayerListController.SetClassifier( m_itemsClassifier );
		m_virtualPlayerListController.SetSource( m_playerItemsDataView );
		m_vendorItemsDataView = new VendorDataView;
		m_vendorDataSource = new ScriptableDataSource;
		m_vendorItemsDataView.BindUIScriptableSystem( m_uiScriptableSystem );
		m_vendorItemsDataView.SetSource( m_vendorDataSource );
		m_vendorItemsDataView.EnableSorting();
		m_vendorItemsDataView.SetVendorGrid( true );
		m_virtualVendorListController = ( ( inkVirtualGridController )( inkVirtualCompoundRef.GetControllerByType( m_vendorInventoryGridList, 'inkVirtualGridController' ) ) );
		m_virtualVendorListController.SetClassifier( m_itemsClassifier );
		m_virtualVendorListController.SetSource( m_vendorItemsDataView );
	}

	private function ReleaseVirtualLists()
	{
		m_virtualPlayerListController.SetClassifier( NULL );
		m_virtualPlayerListController.SetSource( NULL );
		m_playerItemsDataView.SetSource( NULL );
		m_virtualVendorListController.SetSource( NULL );
		m_virtualVendorListController.SetClassifier( NULL );
		m_vendorItemsDataView.SetSource( NULL );
		m_itemsClassifier = NULL;
		m_playerItemsDataView = NULL;
		m_playerDataSource = NULL;
		m_vendorItemsDataView = NULL;
		m_vendorDataSource = NULL;
	}

	private function SetTimeDilatation( enable : Bool )
	{
		var timeSystem : TimeSystem;
		var timeDilationReason : CName;
		timeDilationReason = 'VendorStash';
		timeSystem = GameInstance.GetTimeSystem( m_player.GetGame() );
		if( enable )
		{
			timeSystem.SetTimeDilation( timeDilationReason, 0.0, , 'Linear', 'Linear' );
			timeSystem.SetTimeDilationOnLocalPlayerZero( timeDilationReason, 0.0, , 'Linear', 'Linear' );
		}
		else
		{
			timeSystem.UnsetTimeDilation( timeDilationReason );
			timeSystem.UnsetTimeDilationOnLocalPlayerZero( timeDilationReason );
		}
	}

	protected event OnSetMenuEventDispatcher( menuEventDispatcher : weak< inkMenuEventDispatcher > )
	{
		m_menuEventDispatcher = menuEventDispatcher;
		m_menuEventDispatcher.RegisterToEvent( 'OnBack', this, 'OnBack' );
		m_menuEventDispatcher.RegisterToEvent( 'OnCloseMenu', this, 'OnCloseMenu' );
		m_menuEventDispatcher.RegisterToEvent( 'OnBeforeLeaveScenario', this, 'OnBeforeLeaveScenario' );
		m_menuEventDispatcher.RegisterToEvent( 'OnSetScreenDisplayContext', this, 'OnSetScreenDisplayContext' );
	}

	protected event OnBack( userData : IScriptable )
	{
		if( !( StatusEffectSystem.ObjectHasStatusEffectWithTag( GetPlayerControlledObject(), 'LockInHubMenu' ) ) )
		{
			m_menuEventDispatcher.SpawnEvent( 'OnVendorClose' );
		}
	}

	protected event OnVendorHubMenuChanged( evt : VendorHubMenuChanged )
	{
		m_isActivePanel = evt.item == HubVendorMenuItems.Trade;
	}

	private function SetupDropdown()
	{
		var controller : DropdownListController;
		var playerSortingButtonController, vendorSortingButtonController : DropdownButtonController;
		var sorting : Int32;
		var data : DropdownItemData;
		inkWidgetRef.RegisterToCallback( m_playerSortingButton, 'OnRelease', this, 'OnPlayerSortingButtonClicked' );
		inkWidgetRef.RegisterToCallback( m_vendorSortingButton, 'OnRelease', this, 'OnVendorSortingButtonClicked' );
		controller = ( ( DropdownListController )( inkWidgetRef.GetController( m_sortingDropdown ) ) );
		playerSortingButtonController = ( ( DropdownButtonController )( inkWidgetRef.GetController( m_playerSortingButton ) ) );
		vendorSortingButtonController = ( ( DropdownButtonController )( inkWidgetRef.GetController( m_vendorSortingButton ) ) );
		controller.Setup( this, SortingDropdownData.GetDefaultDropdownOptions() );
		sorting = m_uiScriptableSystem.GetVendorPanelPlayerActiveSorting( ( ( Int32 )( ItemSortMode.Default ) ) );
		data = SortingDropdownData.GetDropdownOption( controller.GetData(), ( ( ItemSortMode )( sorting ) ) );
		playerSortingButtonController.SetData( data );
		m_playerItemsDataView.SetSortMode( ( ( ItemSortMode )data.identifier ) );
		sorting = m_uiScriptableSystem.GetVendorPanelVendorActiveSorting( ( ( Int32 )( ItemSortMode.Default ) ) );
		data = SortingDropdownData.GetDropdownOption( controller.GetData(), ( ( ItemSortMode )( sorting ) ) );
		vendorSortingButtonController.SetData( data );
		m_vendorItemsDataView.SetSortMode( ( ( ItemSortMode )data.identifier ) );
	}

	protected event OnDropdownItemClickedEvent( evt : DropdownItemClickedEvent )
	{
		var identifier : ItemSortMode;
		var data : DropdownItemData;
		var setPlayerSortingRequest : UIScriptableSystemSetVendorPanelPlayerSorting;
		var setVendorSortingRequest : UIScriptableSystemSetVendorPanelVendorSorting;
		identifier = ( ( ItemSortMode )evt.identifier );
		data = SortingDropdownData.GetDropdownOption( ( ( DropdownListController )( inkWidgetRef.GetController( m_sortingDropdown ) ) ).GetData(), identifier );
		if( data )
		{
			if( evt.triggerButton.GetRootWidget() == inkWidgetRef.Get( m_playerSortingButton ) )
			{
				evt.triggerButton.SetData( data );
				m_playerItemsDataView.SetSortMode( identifier );
				setPlayerSortingRequest = new UIScriptableSystemSetVendorPanelPlayerSorting;
				setPlayerSortingRequest.sortMode = ( ( Int32 )( identifier ) );
				m_uiScriptableSystem.QueueRequest( setPlayerSortingRequest );
			}
			else if( evt.triggerButton.GetRootWidget() == inkWidgetRef.Get( m_vendorSortingButton ) )
			{
				evt.triggerButton.SetData( data );
				m_vendorItemsDataView.SetSortMode( identifier );
				setVendorSortingRequest = new UIScriptableSystemSetVendorPanelVendorSorting;
				setVendorSortingRequest.sortMode = ( ( Int32 )( identifier ) );
				m_uiScriptableSystem.QueueRequest( setVendorSortingRequest );
			}
		}
	}

	protected event OnPlayerSortingButtonClicked( evt : inkPointerEvent )
	{
		var controller : DropdownListController;
		if( evt.IsAction( 'click' ) )
		{
			PlaySound( 'Button', 'OnPress' );
			inkWidgetRef.SetTranslation( m_sortingDropdown, Vector2( 1119.0, 268.0 ) );
			controller = ( ( DropdownListController )( inkWidgetRef.GetController( m_sortingDropdown ) ) );
			controller.SetTriggerButton( ( ( DropdownButtonController )( inkWidgetRef.GetController( m_playerSortingButton ) ) ) );
			controller.Toggle();
			OnInventoryItemHoverOut( NULL );
		}
	}

	protected event OnVendorSortingButtonClicked( evt : inkPointerEvent )
	{
		var controller : DropdownListController;
		if( evt.IsAction( 'click' ) )
		{
			PlaySound( 'Button', 'OnPress' );
			inkWidgetRef.SetTranslation( m_sortingDropdown, Vector2( 2650.0, 270.0 ) );
			controller = ( ( DropdownListController )( inkWidgetRef.GetController( m_sortingDropdown ) ) );
			controller.SetTriggerButton( ( ( DropdownButtonController )( inkWidgetRef.GetController( m_vendorSortingButton ) ) ) );
			controller.Toggle();
			OnInventoryItemHoverOut( NULL );
		}
	}

	private function SetFilters( root : inkWidgetRef, const data : ref< array< Int32 > >, callback : CName )
	{
		var radioGroup : FilterRadioGroup;
		radioGroup = ( ( FilterRadioGroup )( inkWidgetRef.GetControllerByType( root, 'FilterRadioGroup' ) ) );
		radioGroup.SetData( data );
		radioGroup.RegisterToCallback( 'OnValueChanged', this, callback );
		if( data.Size() == 1 )
		{
			radioGroup.Toggle( data[ 0 ] );
		}
	}

	private function ToggleFilter( root : inkWidgetRef, data : Int32 )
	{
		var radioGroup : FilterRadioGroup;
		radioGroup = ( ( FilterRadioGroup )( inkWidgetRef.GetControllerByType( root, 'FilterRadioGroup' ) ) );
		radioGroup.ToggleData( data );
	}

	protected event OnFilterRadioItemHoverOver( evt : FilterRadioItemHoverOver )
	{
		var tooltipData : MessageTooltipData;
		tooltipData = new MessageTooltipData;
		tooltipData.Title = NameToString( ItemFilterCategories.GetLabelKey( evt.identifier ) );
		m_TooltipsManager.ShowTooltipAtWidget( 'descriptionTooltip', evt.target, tooltipData, gameuiETooltipPlacement.RightTop, true );
	}

	protected event OnFilterRadioItemHoverOut( evt : FilterRadioItemHoverOut )
	{
		m_TooltipsManager.HideTooltips();
	}

	protected event OnPlayerFilterChange( controller : weak< inkRadioGroupController >, selectedIndex : Int32 )
	{
		var category : ItemFilterCategory;
		category = m_playerFilterManager.GetAt( selectedIndex );
		m_playerItemsDataView.SetFilterType( category );
		m_lastPlayerFilter = category;
		m_playerItemsDataView.SetSortMode( m_playerItemsDataView.GetSortMode() );
		PlayLibraryAnimation( 'player_grid_show' );
		( ( inkScrollController )( inkWidgetRef.GetController( m_playerInventoryGridScroll ) ) ).SetScrollPosition( 0.0 );
	}

	protected event OnVendorFilterChange( controller : weak< inkRadioGroupController >, selectedIndex : Int32 )
	{
		var category : ItemFilterCategory;
		category = m_vendorFilterManager.GetAt( selectedIndex );
		m_vendorItemsDataView.SetFilterType( category );
		m_lastVendorFilter = category;
		m_vendorItemsDataView.SetSortMode( m_vendorItemsDataView.GetSortMode() );
		PlayLibraryAnimation( 'vendor_grid_show' );
		( ( inkScrollController )( inkWidgetRef.GetController( m_vendorInventoryGridScroll ) ) ).SetScrollPosition( 0.0 );
	}

	private function Init()
	{
		m_player = ( ( PlayerPuppet )( GetPlayerControlledObject() ) );
		m_uiScriptableSystem = UIScriptableSystem.GetInstance( m_player.GetGame() );
		m_uiInventorySystem = UIInventoryScriptableSystem.GetInstance( m_player.GetGame() );
		m_playerItemDisplayContext = ItemDisplayContextData.Make( m_player, ItemDisplayContext.VendorPlayer );
		m_vendorItemDisplayContext = ItemDisplayContextData.Make( m_player, ItemDisplayContext.Vendor );
		m_TooltipsManager = ( ( gameuiTooltipsManager )( inkWidgetRef.GetControllerByType( m_TooltipsManagerRef, 'gameuiTooltipsManager' ) ) );
		m_TooltipsManager.Setup( ETooltipsStyle.Menus );
		m_buttonHintsController = ( ( ButtonHints )( SpawnFromExternal( inkWidgetRef.Get( m_buttonHintsManagerRef ), R"base\gameplay\gui\common\buttonhints.inkwidget", 'Root' ).GetController() ) );
		if( !( StatusEffectSystem.ObjectHasStatusEffectWithTag( GetPlayerControlledObject(), 'LockInHubMenu' ) ) )
		{
			m_buttonHintsController.AddButtonHint( 'back', GetLocalizedText( "Common-Access-Close" ) );
		}
		m_InventoryManager = new InventoryDataManagerV2;
		m_InventoryManager.Initialize( m_player );
		m_itemTypeSorting = InventoryDataManagerV2.GetItemTypesForSorting();
		m_VendorDataManager.UpdateOpenTime( m_player.GetGame() );
		m_comparisonResolver = InventoryItemPreferredComparisonResolver.Make( m_uiInventorySystem );
		inkCompoundRef.RemoveAllChildren( m_vendorSpecialOffersInventoryGridList );
		inkVirtualCompoundRef.RemoveAllChildren( m_vendorInventoryGridList );
		inkVirtualCompoundRef.RemoveAllChildren( m_inventoryGridList );
		SetupBB();
		InitializeVirtualLists();
		m_isComparisionDisabled = m_uiScriptableSystem.IsComparisionTooltipDisabled();
		m_buttonHintsController.AddButtonHint( 'toggle_comparison_tooltip', GetLocalizedText( ( ( m_isComparisionDisabled ) ? ( "UI-UserActions-EnableComparison" ) : ( "UI-UserActions-DisableComparison" ) ) ) );
		m_playerFilterManager = ItemCategoryFliterManager.Make();
		m_vendorFilterManager = ItemCategoryFliterManager.Make();
		PlaySound( 'GameMenu', 'OnOpen' );
		SpawnFromExternal( inkWidgetRef.Get( m_notificationRoot ), R"base\gameplay\gui\widgets\activity_log\activity_log_panels.inkwidget", 'RootVert' );
		GameInstance.GetTelemetrySystem( m_player.GetGame() ).LogVendorMenuState( m_VendorDataManager.GetVendorID(), true );
	}

	protected event OnUIVendorItemSoldEvent( evt : UIVendorItemsSoldEvent )
	{
		var i : Int32;
		if( evt.itemsID.Size() < 1 )
		{
			m_transactionPending = false;
			return false;
		}
		for( i = sellQueue.Size() - 1; i >= 0; i -= 1 )
		{
			if( sellQueue[ i ].requestID == evt.requestID )
			{
				sellQueue.Erase( i );
			}
		}
		m_lastVendorFilter = ItemFilterCategory.Buyback;
		m_InventoryManager.MarkToRebuild();
		UpdateVendorMoney();
		UpdatePlayerMoney();
		PopulateVendorInventory();
		ShowHideVendorStock();
		PopulatePlayerInventory();
		m_transactionPending = false;
	}

	protected event OnUIVendorItemBoughtEvent( evt : UIVendorItemsBoughtEvent )
	{
		var category : ItemFilterCategory;
		var i, limit : Int32;
		var itemID : ItemID;
		var itemData : weak< gameItemData >;
		var item : UIInventoryItem;
		for( i = buyQueue.Size() - 1; i >= 0; i -= 1 )
		{
			if( buyQueue[ i ].requestID == evt.requestID )
			{
				buyQueue.Erase( i );
			}
		}
		for( i = 0, limit = evt.itemsID.Size(); i < limit; i += 1 )
		{
			itemID = evt.itemsID[ i ];
			itemData = m_InventoryManager.GetPlayerItemData( itemID );
			item = UIInventoryItem.Make( m_player, itemData );
			if( item.IsQuestItem() )
			{
				m_boughtQuestItems.PushBack( item.GetRealItemData() );
			}
			category = ItemCategoryFliter.GetItemCategoryType( itemData );
			if( category != ItemFilterCategory.Invalid )
			{
				m_lastPlayerFilter = category;
			}
		}
		m_InventoryManager.MarkToRebuild();
		UpdateVendorMoney();
		UpdatePlayerMoney();
		PopulateVendorInventory();
		ShowHideVendorStock();
		PopulatePlayerInventory();
		FlagDLCAddedItemsAsInspected( evt.itemsID );
	}

	private function FlagDLCAddedItemsAsInspected( const itemsID : ref< array< ItemID > > )
	{
		var itemData : weak< gameItemData >;
		var itemInspectedRequest : UIScriptableSystemDLCAddedItemInspected;
		var i, limit : Int32;
		for( i = 0, limit = itemsID.Size(); i < limit; i += 1 )
		{
			itemData = m_InventoryManager.GetPlayerItemData( itemsID[ i ] );
			if( itemData.HasTag( 'DLCAdded' ) )
			{
				itemInspectedRequest = new UIScriptableSystemDLCAddedItemInspected;
				itemInspectedRequest.itemTDBID = ItemID.GetTDBID( itemsID[ i ] );
				m_uiScriptableSystem.QueueRequest( itemInspectedRequest );
			}
		}
	}

	protected event OnCraftingComplete( value : Variant )
	{
		var command : CraftingCommands;
		command = ( ( CraftingCommands )( m_craftingBlackboard.GetVariant( GetAllBlackboardDefs().UI_Crafting.lastCommand ) ) );
		if( command == CraftingCommands.DisassemblingFinished )
		{
			m_InventoryManager.MarkToRebuild();
			UpdateVendorMoney();
			UpdatePlayerMoney();
			PopulateVendorInventory();
			ShowHideVendorStock();
			PopulatePlayerInventory();
		}
	}

	private function SetupBB()
	{
		m_VendorBlackboardDef = GetAllBlackboardDefs().UI_Vendor;
		m_VendorBlackboard = GetBlackboardSystem().Get( m_VendorBlackboardDef );
		if( m_VendorBlackboard )
		{
			m_VendorUpdatedCallbackID = m_VendorBlackboard.RegisterDelayedListenerVariant( m_VendorBlackboardDef.VendorData, this, 'OnVendorUpdated' );
		}
		m_craftingBlackboardDef = GetAllBlackboardDefs().UI_Crafting;
		m_craftingBlackboard = GetBlackboardSystem().Get( m_craftingBlackboardDef );
		if( m_craftingBlackboard )
		{
			m_craftingCallbackID = m_craftingBlackboard.RegisterDelayedListenerVariant( m_craftingBlackboardDef.lastItem, this, 'OnCraftingComplete', true );
		}
		if( m_storageUserData )
		{
			m_InventoryCallback = GetAllBlackboardDefs().UI_Inventory;
			m_InventoryBlackboard = GetBlackboardSystem().Get( m_InventoryCallback );
			if( m_InventoryBlackboard )
			{
				m_InventoryAddedBBID = m_InventoryBlackboard.RegisterDelayedListenerVariant( m_InventoryCallback.itemAdded, this, 'OnInventoryItemAdded', false );
				m_InventoryRemovedBBID = m_InventoryBlackboard.RegisterDelayedListenerVariant( m_InventoryCallback.itemRemoved, this, 'OnInventoryItemRemoved', false );
			}
		}
	}

	private function RemoveBB()
	{
		if( m_VendorBlackboard )
		{
			m_VendorBlackboard.UnregisterDelayedListener( m_VendorBlackboardDef.VendorData, m_VendorUpdatedCallbackID );
		}
		if( m_craftingBlackboard )
		{
			m_craftingBlackboard.UnregisterDelayedListener( m_craftingBlackboardDef.lastItem, m_craftingCallbackID );
		}
		if( m_InventoryBlackboard )
		{
			m_InventoryBlackboard.UnregisterDelayedListener( m_InventoryCallback.itemAdded, m_InventoryAddedBBID );
			m_InventoryBlackboard.UnregisterDelayedListener( m_InventoryCallback.itemRemoved, m_InventoryRemovedBBID );
		}
		m_VendorBlackboard = NULL;
		m_storageBlackboard = NULL;
		m_InventoryBlackboard = NULL;
		m_storageUserData = NULL;
	}

	protected event OnInventoryItemAdded( value : Variant )
	{
		Update();
	}

	protected event OnInventoryItemRemoved( value : Variant )
	{
		Update();
	}

	private function Update()
	{
		m_InventoryManager.MarkToRebuild();
		UpdateVendorMoney();
		UpdatePlayerMoney();
		PopulateVendorInventory();
		ShowHideVendorStock();
		PopulatePlayerInventory();
	}

	private function UpdateVendorMoney()
	{
		var vendorMoney : Int32;
		vendorMoney = MarketSystem.GetVendorMoney( m_VendorDataManager.GetVendorInstance() );
		inkTextRef.SetText( m_vendorMoney, IntToString( vendorMoney ) );
	}

	private function UpdatePlayerMoney()
	{
		inkTextRef.SetText( m_playerMoney, IntToString( VendorDataManager.GetLocalPlayerCurrencyAmount( VendorDataManager.GetLocalPlayer( m_player.GetGame() ) ) ) );
	}

	private function ShowHideVendorStock()
	{
		if( ( inkCompoundRef.GetNumChildren( m_vendorSpecialOffersInventoryGridList ) == 0 ) && ( inkVirtualCompoundRef.GetNumChildren( m_vendorInventoryGridList ) == 0 ) )
		{
		}
		else
		{
		}
	}

	protected event OnInventoryClick( evt : ItemDisplayClickEvent )
	{
		if( evt.uiInventoryItem )
		{
			if( m_vendorUserData )
			{
				HandleVendorSlotClick( evt );
			}
			else if( m_storageUserData )
			{
				HandleStorageSlotClick( evt );
			}
		}
	}

	protected event OnItemDisplayHold( evt : ItemDisplayHoldEvent )
	{
		if( evt.uiInventoryItem )
		{
			if( m_vendorUserData )
			{
				HandleVendorSlotHold( evt );
			}
			else if( m_storageUserData )
			{
				HandleStorageSlotHold( evt );
			}
		}
	}

	protected event OnItemDisplayPress( evt : ItemDisplayPressEvent )
	{
		m_pressedItemDisplay = evt.display;
	}

	protected event OnHandleGlobalPress( evt : inkPointerEvent )
	{
		if( evt.IsAction( 'sell_junk' ) )
		{
			m_globalSellInputPending = true;
		}
	}

	protected event OnHandleGlobalRelease( evt : inkPointerEvent )
	{
		var setComparisionDisabledRequest : UIScriptableSystemSetComparisionTooltipDisabled;
		if( evt.IsAction( 'sell_junk' ) && m_vendorUserData )
		{
			m_globalSellInputPending = false;
			OpenSellJunkConfirmation();
		}
		else if( evt.IsAction( 'toggle_comparison_tooltip' ) )
		{
			m_isComparisionDisabled = !( m_isComparisionDisabled );
			m_buttonHintsController.AddButtonHint( 'toggle_comparison_tooltip', GetLocalizedText( ( ( m_isComparisionDisabled ) ? ( "UI-UserActions-EnableComparison" ) : ( "UI-UserActions-DisableComparison" ) ) ) );
			setComparisionDisabledRequest = new UIScriptableSystemSetComparisionTooltipDisabled;
			setComparisionDisabledRequest.value = m_isComparisionDisabled;
			m_uiScriptableSystem.QueueRequest( setComparisionDisabledRequest );
			InvalidateItemTooltipEvent();
		}
	}

	private function HandleVendorSlotClick( evt : ItemDisplayClickEvent )
	{
		var targetItem : weak< UIInventoryItem >;
		var vendorNotification : UIMenuNotificationEvent;
		var additionalInfo : VendorRequirementsNotMetNotificationData;
		var isIconic : Bool;
		var maxQuantity : Int32;
		var isVendorItem : Bool;
		var tempDummy : SItemStackRequirementData;
		targetItem = evt.uiInventoryItem;
		isVendorItem = evt.displayContextData.GetDisplayContext() == ItemDisplayContext.Vendor;
		if( ( evt.actionName.IsAction( 'click' ) && targetItem ) && !( m_globalSellInputPending ) )
		{
			if( isVendorItem )
			{
				if( false )
				{
					vendorNotification = new UIMenuNotificationEvent;
					vendorNotification.m_notificationType = UIMenuNotificationType.VendorRequirementsNotMet;
					additionalInfo = new VendorRequirementsNotMetNotificationData;
					additionalInfo.m_data = tempDummy;
					vendorNotification.m_additionalInfo = additionalInfo;
					GameInstance.GetUISystem( m_player.GetGame() ).QueueEvent( vendorNotification );
					PlaySound( 'MapPin', 'OnDelete' );
					return;
				}
				maxQuantity = GetMaxQuantity( targetItem, false, evt.isBuybackStack );
				if( maxQuantity == 0 )
				{
					vendorNotification = new UIMenuNotificationEvent;
					vendorNotification.m_notificationType = UIMenuNotificationType.CraftingAmmoCap;
					GameInstance.GetUISystem( m_player.GetGame() ).QueueEvent( vendorNotification );
					PlaySound( 'MapPin', 'OnDelete' );
					return;
				}
				if( maxQuantity == 1 )
				{
					BuyItem( targetItem, maxQuantity, evt.isBuybackStack );
					PlaySound( 'Item', 'OnBuy' );
					PlayRumble( RumbleStrength.Heavy, RumbleType.Pulse, RumblePosition.Right );
					m_TooltipsManager.HideTooltips();
				}
				else
				{
					if( GetPrice( targetItem.GetRealItemData(), QuantityPickerActionType.Buy, 1 ) <= m_VendorDataManager.GetLocalPlayerCurrencyAmount() )
					{
						OpenQuantityPicker( targetItem, QuantityPickerActionType.Buy, evt.isBuybackStack );
					}
				}
			}
			else if( ( !( isVendorItem ) && NotGrenadeOrHealingItem( targetItem ) ) && !( evt.isQuestBought ) )
			{
				if( m_transactionPending )
				{
					return;
				}
				if( evt.display.GetIsPlayerFavourite() )
				{
					vendorNotification = new UIMenuNotificationEvent;
					vendorNotification.m_notificationType = UIMenuNotificationType.InventoryActionBlocked;
					GameInstance.GetUISystem( m_player.GetGame() ).QueueEvent( vendorNotification );
					PlaySound( 'MapPin', 'OnDelete' );
					return;
				}
				if( targetItem.GetQuantity() == 1 )
				{
					if( targetItem.IsEquipped() )
					{
						OpenConfirmationPopup( targetItem, targetItem.GetQuantity(), QuantityPickerActionType.Sell, VendorConfirmationPopupType.EquippedItem );
					}
					else
					{
						isIconic = targetItem.IsIconic();
						if( isIconic )
						{
							OpenConfirmationPopup( targetItem, targetItem.GetQuantity(), QuantityPickerActionType.Sell );
						}
						else
						{
							SellItem( targetItem.GetRealItemData(), targetItem.GetQuantity() );
						}
					}
				}
				else
				{
					OpenQuantityPicker( targetItem, QuantityPickerActionType.Sell, false, true );
				}
			}
		}
		else if( ( evt.actionName.IsAction( 'preview_item' ) && ( targetItem != NULL ) ) && ( m_pressedItemDisplay != NULL ) )
		{
			PlaySound( 'MapPin', 'OnCreate' );
			m_pressedItemDisplay = NULL;
			if( !( targetItem.IsRecipe() ) && ( targetItem.IsWeapon() || targetItem.IsClothing() ) )
			{
				if( m_isPopupPending )
				{
					return;
				}
				m_isPopupPending = true;
				m_itemPreviewPopupToken = ItemPreviewHelper.ShowPreviewItem( this, targetItem, targetItem.IsClothing(), 'OnItemPreviewPopup' );
			}
		}
	}

	private function HandleStorageSlotClick( evt : ItemDisplayClickEvent )
	{
		var targetItem : weak< UIInventoryItem >;
		targetItem = evt.uiInventoryItem;
		if( ( evt.actionName.IsAction( 'click' ) && targetItem ) && NotGrenadeOrHealingItem( targetItem ) )
		{
			if( evt.displayContextData.GetDisplayContext() == ItemDisplayContext.VendorPlayer )
			{
				if( targetItem.GetQuantity() == 1 )
				{
					if( targetItem.IsEquipped() )
					{
						OpenConfirmationPopup( targetItem, targetItem.GetQuantity(), QuantityPickerActionType.TransferToStorage, VendorConfirmationPopupType.StashEquippedItem );
					}
					else
					{
						m_VendorDataManager.TransferItem( m_player, m_VendorDataManager.GetVendorInstance(), targetItem.GetRealItemData(), targetItem.GetQuantity() );
						PlaySound( 'Item', 'OnBuy' );
						PlayRumble( RumbleStrength.Heavy, RumbleType.Pulse, RumblePosition.Right );
						m_TooltipsManager.HideTooltips();
					}
				}
				else
				{
					OpenQuantityPicker( targetItem, QuantityPickerActionType.TransferToStorage );
				}
			}
			else
			{
				if( targetItem.GetQuantity() == 1 )
				{
					m_VendorDataManager.TransferItem( m_VendorDataManager.GetVendorInstance(), m_player, targetItem.GetRealItemData(), targetItem.GetQuantity() );
					PlaySound( 'Item', 'OnSell' );
					PlayRumble( RumbleStrength.Heavy, RumbleType.Pulse, RumblePosition.Left );
				}
				else
				{
					OpenQuantityPicker( targetItem, QuantityPickerActionType.TransferToPlayer );
				}
			}
		}
		else if( ( evt.actionName.IsAction( 'preview_item' ) && ( targetItem != NULL ) ) && ( m_pressedItemDisplay != NULL ) )
		{
			PlaySound( 'MapPin', 'OnCreate' );
			m_pressedItemDisplay = NULL;
			if( !( targetItem.IsRecipe() ) && ( targetItem.IsWeapon() || targetItem.IsClothing() ) )
			{
				m_itemPreviewPopupToken = ItemPreviewHelper.ShowPreviewItem( this, targetItem, targetItem.IsClothing(), 'OnItemPreviewPopup' );
			}
		}
	}

	private function HandleVendorSlotHold( evt : ItemDisplayHoldEvent )
	{
		var targetItem : weak< UIInventoryItem >;
		var setPlayerFavouriteRequest : UIScriptableSystemSetItemPlayerFavourite;
		var isVendorItem : Bool;
		targetItem = evt.uiInventoryItem;
		isVendorItem = evt.displayContextData.GetDisplayContext() == ItemDisplayContext.Vendor;
		if( ( ( ( evt.actionName.IsAction( 'favourite_item' ) && !( isVendorItem ) ) && targetItem ) && targetItem.IsWeapon() ) && ( m_pressedItemDisplay != NULL ) )
		{
			setPlayerFavouriteRequest = new UIScriptableSystemSetItemPlayerFavourite;
			setPlayerFavouriteRequest.itemID = targetItem.ID;
			setPlayerFavouriteRequest.favourite = !( evt.display.GetIsPlayerFavourite() );
			m_uiScriptableSystem.QueueRequest( setPlayerFavouriteRequest );
			evt.display.SetIsPlayerFavourite( setPlayerFavouriteRequest.favourite );
			UpdateFavouriteHint( setPlayerFavouriteRequest.favourite );
			m_pressedItemDisplay = NULL;
			PlaySound( 'MapPin', 'OnEnable' );
			PlayRumble( RumbleStrength.Heavy, RumbleType.Pulse, RumblePosition.Right );
		}
	}

	private function HandleStorageSlotHold( evt : ItemDisplayHoldEvent )
	{
		var targetItem : weak< UIInventoryItem >;
		var setPlayerFavouriteRequest : UIScriptableSystemSetItemPlayerFavourite;
		targetItem = evt.uiInventoryItem;
		if( ( ( evt.actionName.IsAction( 'favourite_item' ) && targetItem ) && targetItem.IsWeapon() ) && ( m_pressedItemDisplay != NULL ) )
		{
			setPlayerFavouriteRequest = new UIScriptableSystemSetItemPlayerFavourite;
			setPlayerFavouriteRequest.itemID = targetItem.ID;
			setPlayerFavouriteRequest.favourite = !( evt.display.GetIsPlayerFavourite() );
			m_uiScriptableSystem.QueueRequest( setPlayerFavouriteRequest );
			evt.display.SetIsPlayerFavourite( setPlayerFavouriteRequest.favourite );
			UpdateFavouriteHint( setPlayerFavouriteRequest.favourite );
			m_pressedItemDisplay = NULL;
			PlaySound( 'MapPin', 'OnEnable' );
			PlayRumble( RumbleStrength.Heavy, RumbleType.Pulse, RumblePosition.Right );
		}
	}

	private function NotGrenadeOrHealingItem( item : UIInventoryItem ) : Bool
	{
		var itemType : gamedataItemType;
		itemType = item.GetItemType();
		if( ( itemType == gamedataItemType.Con_Inhaler || itemType == gamedataItemType.Con_Injector ) || itemType == gamedataItemType.Gad_Grenade )
		{
			return false;
		}
		return true;
	}

	private function OpenSellJunkConfirmation()
	{
		var data : VendorSellJunkPopupData;
		var resultPrice, vendorLimitResultPrice : Float;
		var sellableItems : array< weak< gameItemData > >;
		var vendorLimitSellabelItems : array< VendorJunkSellItem >;
		var vendorMoney : Int32;
		sellableItems = GetSellableJunk();
		if( sellableItems.Size() )
		{
			if( m_isPopupPending )
			{
				return;
			}
			m_isPopupPending = true;
			vendorMoney = MarketSystem.GetVendorMoney( m_VendorDataManager.GetVendorInstance() );
			vendorLimitSellabelItems = GetLimitedSellableItems( sellableItems, vendorMoney );
			resultPrice = GetBulkSellPrice( sellableItems );
			vendorLimitResultPrice = GetBulkSellPrice( vendorLimitSellabelItems );
			data = new VendorSellJunkPopupData;
			data.notificationName = 'base\gameplay\gui\widgets\notifications\vendor_sell_junk_confirmation.inkwidget';
			data.isBlocking = true;
			data.useCursor = true;
			data.queueName = 'modal_popup';
			data.items = sellableItems;
			data.itemsQuantity = sellableItems.Size();
			data.totalPrice = resultPrice;
			data.limitedTotalPrice = ( ( Int32 )( vendorLimitResultPrice ) );
			data.limitedItems = vendorLimitSellabelItems;
			data.limitedItemsQuantity = vendorLimitSellabelItems.Size();
			m_sellJunkPopupToken = ShowGameNotification( data );
			m_sellJunkPopupToken.RegisterListener( this, 'OnSellJunkPopupClosed' );
			m_buttonHintsController.Hide();
		}
	}

	protected event OnSellJunkPopupClosed( data : inkGameNotificationData )
	{
		var i, limit : Int32;
		var sellJunkData : VendorSellJunkPopupCloseData;
		var itemsData : array< weak< gameItemData > >;
		var amounts : array< Int32 >;
		m_isPopupPending = false;
		m_sellJunkPopupToken = NULL;
		sellJunkData = ( ( VendorSellJunkPopupCloseData )( data ) );
		if( sellJunkData.confirm )
		{
			for( i = 0, limit = sellJunkData.limitedItems.Size(); i < limit; i += 1 )
			{
				itemsData.PushBack( sellJunkData.limitedItems[ i ].item );
				amounts.PushBack( sellJunkData.limitedItems[ i ].quantity );
			}
			m_VendorDataManager.SellItemsToVendor( itemsData, amounts );
			PlaySound( 'Item', 'OnSell' );
			m_TooltipsManager.HideTooltips();
		}
		else
		{
			PlaySound( 'Button', 'OnPress' );
		}
		m_buttonHintsController.Show();
	}

	protected event OnItemPreviewPopup( data : inkGameNotificationData )
	{
		m_isPopupPending = false;
		m_itemPreviewPopupToken = NULL;
	}

	private function OpenQuantityPicker( itemData : weak< UIInventoryItem >, actionType : QuantityPickerActionType, optional isBuyback : Bool, optional isPlayerItem : Bool )
	{
		var data : QuantityPickerPopupData;
		data = new QuantityPickerPopupData;
		if( m_isPopupPending )
		{
			return;
		}
		m_isPopupPending = true;
		data.notificationName = 'base\gameplay\gui\widgets\notifications\item_quantity_picker.inkwidget';
		data.isBlocking = true;
		data.useCursor = true;
		data.queueName = 'modal_popup';
		data.maxValue = GetMaxQuantity( itemData, isPlayerItem, isBuyback );
		data.inventoryItem = itemData;
		data.actionType = actionType;
		data.vendor = m_VendorDataManager.GetVendorInstance();
		data.isBuyback = isBuyback;
		m_quantityPickerPopupToken = ShowGameNotification( data );
		m_quantityPickerPopupToken.RegisterListener( this, 'OnQuantityPickerPopupClosed' );
		m_buttonHintsController.Hide();
	}

	private function GetMaxQuantity( item : weak< UIInventoryItem >, optional isPlayerItem : Bool, optional isBuybackStack : Bool ) : Int32
	{
		var result, playerQuantity, ammoCap, vendorQuantity : Int32;
		var tags : array< CName >;
		var gameInstance : GameInstance;
		var player : PlayerPuppet;
		var transactionSystem : TransactionSystem;
		var soldItem : SoldItem;
		gameInstance = m_VendorDataManager.GetVendorInstance().GetGame();
		player = GetPlayer( gameInstance );
		transactionSystem = GameInstance.GetTransactionSystem( gameInstance );
		if( isBuybackStack )
		{
			soldItem = m_vendorSoldItems.GetItem( item.GetID() );
			if( soldItem )
			{
				vendorQuantity = soldItem.quantity;
			}
			else
			{
				vendorQuantity = item.GetQuantity();
			}
		}
		else
		{
			vendorQuantity = item.GetQuantity();
		}
		if( isPlayerItem )
		{
			return vendorQuantity;
		}
		tags = item.GetItemRecord().Tags();
		if( ( tags.Contains( 'Grenade' ) || tags.Contains( 'Injector' ) ) || tags.Contains( 'Inhaler' ) )
		{
			return 1;
		}
		if( !( tags.Contains( 'Ammo' ) ) )
		{
			return vendorQuantity;
		}
		playerQuantity = transactionSystem.GetItemQuantity( player, item.GetID() );
		ammoCap = ( ( Int32 )( item.GetItemData().GetStatValueByType( gamedataStatType.Quantity ) ) );
		result = Min( ammoCap - playerQuantity, vendorQuantity );
		return result;
	}

	protected event OnQuantityPickerPopupClosed( data : inkGameNotificationData )
	{
		var quantityData : QuantityPickerPopupCloseData;
		var isLegendary, isIconic : Bool;
		m_isPopupPending = false;
		m_quantityPickerPopupToken = NULL;
		quantityData = ( ( QuantityPickerPopupCloseData )( data ) );
		if( quantityData.choosenQuantity != -1 )
		{
			switch( quantityData.actionType )
			{
				case QuantityPickerActionType.TransferToStorage:
					m_VendorDataManager.TransferItem( m_player, m_VendorDataManager.GetVendorInstance(), quantityData.inventoryItem.GetRealItemData(), quantityData.choosenQuantity );
				PlaySound( 'Item', 'OnSell' );
				m_TooltipsManager.HideTooltips();
				PopulateInventories();
				break;
				case QuantityPickerActionType.TransferToPlayer:
					m_VendorDataManager.TransferItem( m_VendorDataManager.GetVendorInstance(), m_player, quantityData.inventoryItem.GetRealItemData(), quantityData.choosenQuantity );
				PlaySound( 'Item', 'OnSell' );
				m_TooltipsManager.HideTooltips();
				PopulateInventories();
				break;
				case QuantityPickerActionType.Buy:
					if( quantityData.isBuyback )
					{
						BuyItem( quantityData.inventoryItem, quantityData.choosenQuantity, true );
					}
					else
					{
						BuyItem( quantityData.inventoryItem, quantityData.choosenQuantity );
					}
				PlaySound( 'Item', 'OnBuy' );
				PlayRumble( RumbleStrength.Heavy, RumbleType.Pulse, RumblePosition.Right );
				m_TooltipsManager.HideTooltips();
				break;
				case QuantityPickerActionType.Sell:
					isLegendary = quantityData.inventoryItem.GetQualityInt() >= UIItemsHelper.QualityEnumToInt( gamedataQuality.Legendary );
				isIconic = RPGManager.IsItemIconic( quantityData.inventoryItem.GetItemData() );
				if( isLegendary || isIconic )
				{
					OpenConfirmationPopup( quantityData.inventoryItem, quantityData.choosenQuantity, quantityData.actionType );
				}
				else
				{
					SellItem( quantityData.inventoryItem.GetRealItemData(), quantityData.choosenQuantity );
					PlaySound( 'Item', 'OnSell' );
					m_TooltipsManager.HideTooltips();
				}
				break;
			}
		}
		m_buttonHintsController.Show();
		PlaySound( 'Button', 'OnPress' );
	}

	private function GetPrice( item : gameItemData, actionType : QuantityPickerActionType, quantity : Int32 ) : Int32
	{
		if( actionType == QuantityPickerActionType.Buy )
		{
			return MarketSystem.GetBuyPrice( m_VendorDataManager.GetVendorInstance(), item.GetID() ) * quantity;
		}
		return RPGManager.CalculateSellPrice( m_VendorDataManager.GetVendorInstance().GetGame(), m_VendorDataManager.GetVendorInstance(), item.GetID() ) * quantity;
	}

	private function OpenConfirmationPopup( itemData : weak< UIInventoryItem >, quantity : Int32, actionType : QuantityPickerActionType, optional type : VendorConfirmationPopupType )
	{
		var data : VendorConfirmationPopupData;
		if( m_isPopupPending )
		{
			return;
		}
		m_isPopupPending = true;
		data = new VendorConfirmationPopupData;
		data.notificationName = 'base\gameplay\gui\widgets\notifications\vendor_confirmation.inkwidget';
		data.isBlocking = true;
		data.useCursor = true;
		data.queueName = 'modal_popup';
		data.inventoryItem = itemData;
		data.quantity = quantity;
		data.type = type;
		data.price = GetPrice( itemData.GetRealItemData(), actionType, quantity );
		m_confirmationPopupToken = ShowGameNotification( data );
		m_confirmationPopupToken.RegisterListener( this, 'OnConfirmationPopupClosed' );
		m_buttonHintsController.Hide();
		m_transactionPending = true;
	}

	protected event OnConfirmationPopupClosed( data : inkGameNotificationData )
	{
		var resultData : VendorConfirmationPopupCloseData;
		m_isPopupPending = false;
		m_confirmationPopupToken = NULL;
		resultData = ( ( VendorConfirmationPopupCloseData )( data ) );
		if( resultData.confirm )
		{
			if( resultData.type == VendorConfirmationPopupType.StashEquippedItem )
			{
				m_VendorDataManager.TransferItem( m_player, m_VendorDataManager.GetVendorInstance(), resultData.inventoryItem.GetRealItemData(), resultData.quantity );
				PlaySound( 'Item', 'OnBuy' );
				PlayRumble( RumbleStrength.Heavy, RumbleType.Pulse, RumblePosition.Right );
				m_TooltipsManager.HideTooltips();
			}
			else
			{
				SellItem( resultData.inventoryItem.GetRealItemData(), resultData.quantity );
			}
		}
		else
		{
			m_transactionPending = false;
		}
		m_buttonHintsController.Show();
		PlaySound( 'Button', 'OnPress' );
	}

	private function SellItem( itemData : gameItemData, quantity : Int32 )
	{
		var itemID : ItemID;
		var queueEntry : VenodrRequestQueueEntry;
		itemID = itemData.GetID();
		if( !( IsSellRequestInQueue( itemID ) ) && m_VendorDataManager.CanPlayerSellItem( itemID ) )
		{
			m_lastRequestId += 1;
			queueEntry = new VenodrRequestQueueEntry;
			queueEntry.requestID = m_lastRequestId;
			queueEntry.itemID = itemID;
			sellQueue.PushBack( queueEntry );
			m_VendorDataManager.SellItemToVendor( itemData, quantity, queueEntry.requestID );
			PlaySound( 'Item', 'OnSell' );
			m_TooltipsManager.HideTooltips();
			m_transactionPending = true;
		}
		else
		{
			m_transactionPending = false;
		}
	}

	private function IsBuyRequestInQueue( itemID : ItemID ) : Bool
	{
		var i : Int32;
		for( i = 0; i < buyQueue.Size(); i += 1 )
		{
			if( buyQueue[ i ].itemID == itemID )
			{
				return true;
			}
		}
		return false;
	}

	private function IsSellRequestInQueue( itemID : ItemID ) : Bool
	{
		var i : Int32;
		for( i = 0; i < sellQueue.Size(); i += 1 )
		{
			if( sellQueue[ i ].itemID == itemID )
			{
				return true;
			}
		}
		return false;
	}

	private function BuyItem( item : UIInventoryItem, quantity : Int32, optional buyback : Bool )
	{
		var itemID : ItemID;
		var queueEntry : VenodrRequestQueueEntry;
		itemID = item.GetID();
		if( !( IsBuyRequestInQueue( itemID ) ) )
		{
			m_lastRequestId += 1;
			queueEntry = new VenodrRequestQueueEntry;
			queueEntry.requestID = m_lastRequestId;
			queueEntry.itemID = itemID;
			buyQueue.PushBack( queueEntry );
			if( buyback )
			{
				m_VendorDataManager.BuybackItemFromVendor( item.GetRealItemData(), quantity, queueEntry.requestID );
			}
			else
			{
				m_VendorDataManager.BuyItemFromVendor( item.GetRealItemData(), quantity, queueEntry.requestID );
			}
		}
	}

	private function FilterOutDuplicateVendorItems( const items : ref< array< VendorGameItemData > > ) : array< VendorGameItemData >
	{
		var i, limit : Int32;
		var alreadyAdded : array< ItemID >;
		var result : array< VendorGameItemData >;
		for( i = 0, limit = items.Size(); i < limit; i += 1 )
		{
			if( !( alreadyAdded.Contains( items[ i ].itemStack.itemID ) ) )
			{
				result.PushBack( items[ i ] );
				alreadyAdded.PushBack( items[ i ].itemStack.itemID );
			}
		}
		return result;
	}

	[ profile = "[UI] Vendor: PopulateVendorInventory" ]
	private function PopulateVendorInventory()
	{
		var items : array< IScriptable >;
		var itemData : VendorUIInventoryItemData;
		var i, limit : Int32;
		var vendorObject : weak< GameObject >;
		var vendorInventoryItems : array< VendorGameItemData >;
		var vendorItemQuantity : Int32;
		var soldItem : SoldItem;
		var buybackItemData : VendorUIInventoryItemData;
		var buybackSellingPrice : Int32;
		var playerCurrencyAmount : Int32;
		var wardrobeItemIDs : array< ItemID >;
		var wardrobeItemAppearances : array< CName >;
		var isAnyNewAppearance : Bool;
		var itemRecord : weak< Item_Record >;
		var storageItems : array< gameItemData >;
		m_vendorUIInventoryItems.Clear();
		m_vendorFilterManager.Clear();
		m_vendorFilterManager.AddFilter( ItemFilterCategory.AllItems );
		if( m_vendorUserData )
		{
			wardrobeItemIDs = GameInstance.GetWardrobeSystem( m_player.GetGame() ).GetStoredItemIDs();
			for( i = 0, limit = wardrobeItemIDs.Size(); i < limit; i += 1 )
			{
				itemRecord = TweakDBInterface.GetItemRecord( ItemID.GetTDBID( wardrobeItemIDs[ i ] ) );
				wardrobeItemAppearances.PushBack( itemRecord.AppearanceName() );
			}
			playerCurrencyAmount = m_VendorDataManager.GetLocalPlayerCurrencyAmount();
			vendorObject = m_VendorDataManager.GetVendorInstance();
			vendorInventoryItems = FilterOutDuplicateVendorItems( m_VendorDataManager.GetVendorInventoryItems() );
			m_vendorSoldItems = m_VendorDataManager.GetVendorSoldItems();
			for( i = 0, limit = vendorInventoryItems.Size(); i < limit; i += 1 )
			{
				m_vendorUIInventoryItems.PushBack( UIInventoryItem.Make( vendorObject, vendorInventoryItems[ i ].gameItemData, m_uiInventorySystem.GetInventoryItemsManager() ) );
				soldItem = m_vendorSoldItems.GetItem( m_vendorUIInventoryItems[ i ].GetID() );
				itemData = new VendorUIInventoryItemData;
				itemData.Item = m_vendorUIInventoryItems[ i ];
				itemData.IsVendorItem = true;
				itemData.DisplayContextData = m_vendorItemDisplayContext;
				itemData.IsDLCAddedActiveItem = m_uiScriptableSystem.IsDLCAddedActiveItem( itemData.Item.GetTweakDBID() );
				if( !( itemData.Item.IsRecipe() ) )
				{
					itemData.ComparisonState = GetComparisonState( itemData.Item );
					if( itemData.Item.IsClothing() )
					{
						itemData.IsNotInWardrobe = !( wardrobeItemAppearances.Contains( itemData.Item.GetItemRecord().AppearanceName() ) );
						if( itemData.IsNotInWardrobe )
						{
							isAnyNewAppearance = true;
						}
					}
				}
				if( soldItem )
				{
					buybackSellingPrice = m_VendorDataManager.GetSellingPrice( itemData.Item.GetID() );
					vendorItemQuantity = itemData.Item.GetQuantity();
					if( soldItem.quantity == vendorItemQuantity )
					{
						itemData.IsBuybackStack = true;
					}
					else if( vendorItemQuantity > soldItem.quantity )
					{
						itemData.Item.SetQuantity( vendorItemQuantity - soldItem.quantity );
						buybackItemData = new VendorUIInventoryItemData;
						buybackItemData.Item = itemData.Item;
						buybackItemData.ItemPrice = ( ( Float )( buybackSellingPrice ) );
						buybackItemData.IsVendorItem = true;
						buybackItemData.IsBuybackStack = true;
						buybackItemData.IsEnoughMoney = playerCurrencyAmount >= ( ( Int32 )( buybackItemData.ItemPrice ) );
						buybackItemData.ComparisonState = itemData.ComparisonState;
						buybackItemData.OverrideQuantity = soldItem.quantity;
						buybackItemData.DisplayContextData = m_vendorItemDisplayContext;
						items.PushBack( buybackItemData );
						m_vendorFilterManager.AddItem( buybackItemData.Item.GetFilterCategory() );
					}
					m_vendorFilterManager.AddFilter( ItemFilterCategory.Buyback );
				}
				else
				{
					m_vendorFilterManager.AddItem( itemData.Item.GetFilterCategory() );
				}
				itemData.ItemPrice = ( ( itemData.IsBuybackStack ) ? ( ( ( Float )buybackSellingPrice ) ) : ( ( ( Float )( m_VendorDataManager.GetBuyingPrice( itemData.Item.GetID() ) ) ) ) );
				itemData.IsEnoughMoney = playerCurrencyAmount >= ( ( Int32 )( itemData.ItemPrice ) );
				items.PushBack( itemData );
			}
			if( isAnyNewAppearance )
			{
				m_vendorFilterManager.AddFilter( ItemFilterCategory.NewWardrobeAppearances );
			}
		}
		else if( m_storageUserData )
		{
			storageItems = m_VendorDataManager.GetStorageItems();
			vendorObject = m_VendorDataManager.GetVendorInstance();
			for( i = 0, limit = storageItems.Size(); i < limit; i += 1 )
			{
				if( !( InventoryDataManagerV2.IsItemBlacklisted( storageItems[ i ] ) ) )
				{
					storageItems[ i ].ReinitializePlayerStats( m_player.GetGame(), m_player.GetEntityID() );
					itemData = new VendorUIInventoryItemData;
					itemData.Item = UIInventoryItem.Make( vendorObject, storageItems[ i ], m_uiInventorySystem.GetInventoryItemsManager() );
					itemData.IsVendorItem = true;
					itemData.IsEnoughMoney = true;
					itemData.ComparisonState = GetComparisonState( itemData.Item );
					itemData.DisplayContextData = m_vendorItemDisplayContext;
					items.PushBack( itemData );
					m_vendorUIInventoryItems.PushBack( itemData.Item );
				}
			}
		}
		m_vendorDataSource.Reset( items );
		m_vendorFilterManager.SortFiltersList();
		m_vendorFilterManager.InsertFilter( 0, ItemFilterCategory.AllItems );
		SetFilters( m_vendorFiltersContainer, m_vendorFilterManager.GetIntFiltersList(), 'OnVendorFilterChange' );
		m_vendorItemsDataView.EnableSorting();
		m_vendorItemsDataView.SetFilterType( m_lastVendorFilter );
		m_vendorItemsDataView.SetSortMode( m_vendorItemsDataView.GetSortMode() );
		m_vendorItemsDataView.DisableSorting();
		ToggleFilter( m_vendorFiltersContainer, ( ( Int32 )( m_lastVendorFilter ) ) );
		inkWidgetRef.SetVisible( m_vendorFiltersContainer, items.Size() > 0 );
		PlayLibraryAnimation( 'vendor_grid_show' );
	}

	private function GetSellableJunk() : array< weak< gameItemData > >
	{
		var i : Int32;
		var result : array< weak< gameItemData > >;
		var sellableItems : array< weak< gameItemData > >;
		var type : gamedataItemType;
		sellableItems = m_VendorDataManager.GetItemsPlayerCanSellFast( ( ( weak< weak< GameObject > > )( m_player ) ) );
		for( i = 0; i < sellableItems.Size(); i += 1 )
		{
			type = RPGManager.GetItemRecord( sellableItems[ i ].GetID() ).ItemType().Type();
			if( type == gamedataItemType.Gen_Junk || type == gamedataItemType.Gen_Jewellery )
			{
				result.PushBack( sellableItems[ i ] );
			}
		}
		return result;
	}

	private function GetLimitedSellableItems( const items : ref< array< weak< gameItemData > > >, moneyLimit : Int32 ) : array< VendorJunkSellItem >
	{
		var i, j, moneyLeft, itemPrice, quantityLeft : Int32;
		var result : array< VendorJunkSellItem >;
		var currentResultItem : VendorJunkSellItem;
		var itemId : ItemID;
		moneyLeft = moneyLimit;
		for( i = 0; i < items.Size(); i += 1 )
		{
			quantityLeft = items[ i ].GetQuantity();
			itemId = items[ i ].GetID();
			if( !( m_VendorDataManager.CanPlayerSellItem( itemId ) ) )
			{
				continue;
			}
			itemPrice = m_VendorDataManager.GetSellingPrice( itemId );
			while( ( moneyLeft >= itemPrice ) && ( quantityLeft > 0 ) )
			{
				for( j = 0; j < result.Size(); j += 1 )
				{
					if( result[ j ].item.GetID() == itemId )
					{
						currentResultItem = result[ j ];
					}
				}
				if( currentResultItem == NULL )
				{
					currentResultItem = new VendorJunkSellItem;
					currentResultItem.item = items[ i ];
					result.PushBack( currentResultItem );
				}
				currentResultItem.quantity += 1;
				moneyLeft -= itemPrice;
				quantityLeft -= 1;
				currentResultItem = NULL;
			}
		}
		return result;
	}

	private function GetBulkSellPrice( const items : ref< array< weak< gameItemData > > > ) : Float
	{
		var i : Int32;
		var unitPrice, sum : Float;
		for( i = 0; i < items.Size(); i += 1 )
		{
			unitPrice = ( ( Float )( m_VendorDataManager.GetSellingPrice( items[ i ].GetID() ) ) );
			sum += ( unitPrice * ( ( Float )( items[ i ].GetQuantity() ) ) );
		}
		return sum;
	}

	private function GetBulkSellPrice( const items : ref< array< VendorJunkSellItem > > ) : Float
	{
		var i : Int32;
		var unitPrice, sum : Float;
		for( i = 0; i < items.Size(); i += 1 )
		{
			unitPrice = ( ( Float )( m_VendorDataManager.GetSellingPrice( items[ i ].item.GetID() ) ) );
			sum += ( unitPrice * ( ( Float )( items[ i ].quantity ) ) );
		}
		return sum;
	}

	[ profile = "[UI] Vendor: PopulatePlayerInventory" ]
	private function PopulatePlayerInventory()
	{
		var i, limit : Int32;
		var items : array< IScriptable >;
		var playerItems : inkHashMap;
		var sellableItems : array< weak< gameItemData > >;
		var vendorUIInventoryItemData : VendorUIInventoryItemData;
		var hasJunkItems : Bool;
		var questItemsHidden : Bool;
		var item : weak< UIInventoryItem >;
		var stashBlacklistedTags : array< CName >;
		var values : array< weak< IScriptable > >;
		m_playerFilterManager.Clear();
		m_playerFilterManager.AddFilter( ItemFilterCategory.AllItems );
		if( m_vendorUserData )
		{
			sellableItems = m_VendorDataManager.GetItemsPlayerCanSellFast( ( ( weak< weak< GameObject > > )( m_player ) ) );
			questItemsHidden = m_VendorDataManager.ArePlayerQuestItemsHidden();
			for( i = 0, limit = sellableItems.Size(); i < limit; i += 1 )
			{
				if( ItemID.HasFlag( sellableItems[ i ].GetID(), gameEItemIDFlag.Preview ) )
				{
					continue;
				}
				vendorUIInventoryItemData = new VendorUIInventoryItemData;
				vendorUIInventoryItemData.Item = m_uiInventorySystem.GetPlayerItemFromAnySource( sellableItems[ i ] );
				vendorUIInventoryItemData.IsVendorItem = false;
				vendorUIInventoryItemData.ItemPrice = ( ( Float )( m_VendorDataManager.GetSellingPrice( sellableItems[ i ].GetID() ) ) );
				vendorUIInventoryItemData.DisplayContextData = m_playerItemDisplayContext;
				items.PushBack( vendorUIInventoryItemData );
				m_playerFilterManager.AddItem( vendorUIInventoryItemData.Item.GetFilterCategory() );
				if( ( !( hasJunkItems ) && vendorUIInventoryItemData.Item.GetItemType() == gamedataItemType.Gen_Junk ) || vendorUIInventoryItemData.Item.GetItemType() == gamedataItemType.Gen_Jewellery )
				{
					hasJunkItems = true;
				}
			}
			if( questItemsHidden )
			{
				for( i = 0, limit = m_boughtQuestItems.Size(); i < limit; i += 1 )
				{
					vendorUIInventoryItemData = new VendorUIInventoryItemData;
					vendorUIInventoryItemData.Item = m_uiInventorySystem.GetPlayerItemFromAnySource( m_boughtQuestItems[ i ] );
					if( vendorUIInventoryItemData.Item.GetOwner() == m_player )
					{
						vendorUIInventoryItemData.IsVendorItem = false;
						vendorUIInventoryItemData.IsQuestBought = true;
						vendorUIInventoryItemData.ItemPrice = ( ( Float )( m_VendorDataManager.GetSellingPrice( m_boughtQuestItems[ i ].GetID() ) ) );
						vendorUIInventoryItemData.DisplayContextData = m_playerItemDisplayContext;
						items.PushBack( vendorUIInventoryItemData );
					}
				}
			}
			if( hasJunkItems )
			{
				m_buttonHintsController.AddButtonHint( 'sell_junk', GetLocalizedText( "UI-UserActions-SellJunk" ) );
			}
			else
			{
				m_buttonHintsController.RemoveButtonHint( 'sell_junk' );
			}
		}
		else if( m_storageUserData )
		{
			m_uiInventorySystem.FlushTempData();
			playerItems = m_uiInventorySystem.GetPlayerItemsMap();
			stashBlacklistedTags = UIInventoryItemsManager.GetStashBlacklistedTags();
			playerItems.GetValues( values );
			for( i = 0, limit = values.Size(); i < limit; i += 1 )
			{
				item = ( ( UIInventoryItem )( values[ i ] ) );
				if( ItemID.HasFlag( item.GetID(), gameEItemIDFlag.Preview ) )
				{
					continue;
				}
				if( item.GetRealItemData().HasAnyOfTags( stashBlacklistedTags ) )
				{
					continue;
				}
				vendorUIInventoryItemData = new VendorUIInventoryItemData;
				vendorUIInventoryItemData.Item = ( ( UIInventoryItem )( values[ i ] ) );
				vendorUIInventoryItemData.IsVendorItem = false;
				vendorUIInventoryItemData.ComparisonState = GetComparisonState( vendorUIInventoryItemData.Item );
				vendorUIInventoryItemData.DisplayContextData = m_playerItemDisplayContext;
				items.PushBack( vendorUIInventoryItemData );
				m_playerFilterManager.AddItem( vendorUIInventoryItemData.Item.GetItemData() );
			}
		}
		m_playerDataSource.Reset( items );
		SetFilters( m_playerFiltersContainer, m_playerFilterManager.GetSortedIntFiltersList(), 'OnPlayerFilterChange' );
		if( m_lastPlayerFilter == ItemFilterCategory.Invalid || !( m_playerFilterManager.Contains( m_lastPlayerFilter ) ) )
		{
			m_lastPlayerFilter = m_playerFilterManager.GetAt( 0 );
		}
		if( m_lastPlayerFilter == ItemFilterCategory.Invalid )
		{
			m_lastPlayerFilter = ItemFilterCategory.AllItems;
		}
		m_playerItemsDataView.EnableSorting();
		m_playerItemsDataView.SetFilterType( m_lastPlayerFilter );
		m_playerItemsDataView.SetSortMode( m_playerItemsDataView.GetSortMode() );
		m_playerItemsDataView.DisableSorting();
		ToggleFilter( m_playerFiltersContainer, ( ( Int32 )( m_lastPlayerFilter ) ) );
		PlayLibraryAnimation( 'player_grid_show' );
	}

	private function PopulateInventories()
	{
		PopulateVendorInventory();
		PopulatePlayerInventory();
	}

	private function GetComparisonState( item : weak< UIInventoryItem > ) : ItemComparisonState
	{
		if( m_comparisonResolver.IsComparable( item ) )
		{
			return m_comparisonResolver.GetItemComparisonState( item );
		}
		return ItemComparisonState.Default;
	}

	private function PrepareTooltips()
	{
		m_TooltipsManager = ( ( gameuiTooltipsManager )( inkWidgetRef.GetControllerByType( m_TooltipsManagerRef, 'gameuiTooltipsManager' ) ) );
		m_TooltipsManager.Setup( ETooltipsStyle.Menus );
	}

	private function InvalidateItemTooltipEvent()
	{
		if( m_lastItemHoverOverEvent != NULL )
		{
			OnInventoryItemHoverOver( m_lastItemHoverOverEvent );
		}
	}

	protected event OnInventoryItemHoverOver( evt : ItemDisplayHoverOverEvent )
	{
		var controller : DropdownListController;
		var localizedHint : String;
		var inventoryItemToComapre : weak< UIInventoryItem >;
		controller = ( ( DropdownListController )( inkWidgetRef.GetController( m_sortingDropdown ) ) );
		m_lastItemHoverOverEvent = evt;
		m_cursorData = new MenuCursorUserData;
		m_cursorData.SetAnimationOverride( 'hoverOnHoldToComplete' );
		if( !( controller.IsOpened() ) )
		{
			inventoryItemToComapre = m_comparisonResolver.GetPreferredComparisonItem( evt.uiInventoryItem );
			ShowTooltipForUIInventoryItem( evt.widget, evt.uiInventoryItem, inventoryItemToComapre, evt.isBuybackStack );
			if( evt.uiInventoryItem != NULL )
			{
				if( ( evt.uiInventoryItem.IsWeapon() || evt.uiInventoryItem.IsClothing() ) && !( evt.uiInventoryItem.IsRecipe() ) )
				{
					m_buttonHintsController.AddButtonHint( 'preview_item', GetLocalizedText( "UI-UserActions-ItemPreview" ) );
				}
				if( evt.uiInventoryItem.IsWeapon() && ( evt.displayContextData.GetDisplayContext() == ItemDisplayContext.VendorPlayer || m_storageUserData ) )
				{
					UpdateFavouriteHint( m_uiScriptableSystem.IsItemPlayerFavourite( evt.uiInventoryItem.GetID() ) );
				}
			}
			if( ( evt.displayContextData.GetDisplayContext() == ItemDisplayContext.Vendor && !( m_storageUserData ) ) && m_vendorUserData )
			{
				localizedHint = GetLocalizedText( "LocKey#17847" );
				m_buttonHintsController.AddButtonHint( 'select', localizedHint );
			}
			else
			{
				if( ( ( ( m_VendorDataManager.CanPlayerSellItem( evt.uiInventoryItem.GetID() ) && !( m_storageUserData ) ) && m_vendorUserData ) && NotGrenadeOrHealingItem( evt.uiInventoryItem ) ) && !( evt.isQuestBought ) )
				{
					localizedHint = GetLocalizedText( "LocKey#17848" );
					m_buttonHintsController.AddButtonHint( 'select', localizedHint );
				}
				if( m_storageUserData && !( m_vendorUserData ) )
				{
					localizedHint = LocKeyToString( 'UI-UserActions-TransferItem' );
					m_buttonHintsController.AddButtonHint( 'select', localizedHint );
				}
			}
			if( evt.uiInventoryItem != NULL )
			{
				if( m_cursorData.GetActionsListSize() >= 0 )
				{
					SetCursorContext( 'Hover', m_cursorData );
				}
				else
				{
					SetCursorContext( 'Hover' );
				}
			}
			else
			{
				SetCursorContext( 'Default' );
			}
		}
	}

	private function UpdateFavouriteHint( state : Bool )
	{
		if( state )
		{
			m_buttonHintsController.AddButtonHint( 'favourite_item', ( ( "[" + GetLocalizedText( "Gameplay-Devices-Interactions-Helpers-Hold" ) ) + "] " ) + GetLocalizedText( "UI-UserActions-ItemRemoveFavourite" ) );
			m_cursorData.AddUniqueAction( 'favourite_item' );
		}
		else
		{
			m_buttonHintsController.AddButtonHint( 'favourite_item', ( ( "[" + GetLocalizedText( "Gameplay-Devices-Interactions-Helpers-Hold" ) ) + "] " ) + GetLocalizedText( "UI-UserActions-ItemAddFavourite" ) );
			m_cursorData.AddUniqueAction( 'favourite_item' );
		}
		if( m_cursorData.GetActionsListSize() >= 0 )
		{
			SetCursorContext( 'Hover', m_cursorData );
		}
		else
		{
			SetCursorContext( 'Hover' );
		}
	}

	protected event OnInventoryDLCAddedItemHoverOver( evt : DLCAddedItemDisplayHoverOverEvent )
	{
		var itemInspectedRequest : UIScriptableSystemDLCAddedItemInspected;
		itemInspectedRequest = new UIScriptableSystemDLCAddedItemInspected;
		itemInspectedRequest.itemTDBID = evt.itemTDBID;
		m_uiScriptableSystem.QueueRequest( itemInspectedRequest );
	}

	private function ShowTooltipForUIInventoryItem( widget : weak< inkWidget >, inspectedItem : weak< UIInventoryItem >, equippedItem : weak< UIInventoryItem >, isBuybackStack : Bool )
	{
		var placement : gameuiETooltipPlacement;
		var isPlayerItem, isComparable : Bool;
		var tooltipsData : array< ATooltipData >;
		var data : UIInventoryItemTooltipWrapper;
		var itemTooltips : CName[ 2 ];
		isPlayerItem = inspectedItem.GetOwner().GetEntityID() == m_player.GetEntityID();
		placement = ( ( isPlayerItem ) ? ( gameuiETooltipPlacement.RightTop ) : ( gameuiETooltipPlacement.LeftTop ) );
		m_TooltipsManager.HideTooltips();
		if( inspectedItem.IsWeapon() )
		{
			itemTooltips[ 0 ] = 'newItemTooltip';
			itemTooltips[ 1 ] = 'newItemTooltipComparision';
		}
		else
		{
			itemTooltips[ 0 ] = 'itemTooltip';
			itemTooltips[ 1 ] = 'itemTooltipComparision';
		}
		if( inspectedItem )
		{
			inspectedItem.GetStatsManagerPure().FlushComparedBars();
			isComparable = ( !( inspectedItem.IsRecipe() ) && inspectedItem.GetItemType() != gamedataItemType.Prt_Program ) && inspectedItem.GetEquipmentArea() != gamedataEquipmentArea.SystemReplacementCW;
			if( equippedItem && isComparable )
			{
				if( isPlayerItem )
				{
					data = UIInventoryItemTooltipWrapper.Make( inspectedItem, m_playerItemDisplayContext );
					if( !( m_isComparisionDisabled ) )
					{
						data.m_comparisonData = UIInventoryItemComparisonManager.Make( inspectedItem, equippedItem );
					}
					tooltipsData.PushBack( IdentifiedWrappedTooltipData.Make( itemTooltips[ 0 ], data ) );
					if( !( m_isComparisionDisabled ) )
					{
						data = UIInventoryItemTooltipWrapper.Make( equippedItem, m_playerItemDisplayContext );
						data.m_comparisonData = UIInventoryItemComparisonManager.Make( equippedItem, inspectedItem );
						tooltipsData.PushBack( IdentifiedWrappedTooltipData.Make( itemTooltips[ 1 ], data ) );
					}
				}
				else
				{
					if( !( m_isComparisionDisabled ) )
					{
						data = UIInventoryItemTooltipWrapper.Make( equippedItem, m_playerItemDisplayContext );
						data.m_comparisonData = UIInventoryItemComparisonManager.Make( equippedItem, inspectedItem );
						tooltipsData.PushBack( IdentifiedWrappedTooltipData.Make( itemTooltips[ 0 ], data ) );
					}
					data = UIInventoryItemTooltipWrapper.Make( inspectedItem, ( ( m_storageUserData ) ? ( m_playerItemDisplayContext ) : ( m_vendorItemDisplayContext ) ) );
					if( !( m_isComparisionDisabled ) )
					{
						data.m_comparisonData = UIInventoryItemComparisonManager.Make( inspectedItem, equippedItem );
					}
					if( isBuybackStack )
					{
						data.m_overridePrice = RPGManager.CalculateSellPrice( m_VendorDataManager.GetVendorInstance().GetGame(), m_VendorDataManager.GetVendorInstance(), inspectedItem.GetID() );
					}
					tooltipsData.PushBack( IdentifiedWrappedTooltipData.Make( itemTooltips[ 1 ], data ) );
				}
				m_TooltipsManager.ShowTooltipsAtWidget( tooltipsData, widget, placement );
			}
			else
			{
				data = UIInventoryItemTooltipWrapper.Make( inspectedItem, ( ( isPlayerItem || m_storageUserData ) ? ( m_playerItemDisplayContext ) : ( m_vendorItemDisplayContext ) ) );
				if( isBuybackStack )
				{
					data.m_overridePrice = RPGManager.CalculateSellPrice( m_VendorDataManager.GetVendorInstance().GetGame(), m_VendorDataManager.GetVendorInstance(), inspectedItem.GetID() );
				}
				if( inspectedItem.GetItemType() == gamedataItemType.Prt_Program )
				{
					m_TooltipsManager.ShowTooltipAtWidget( 'programTooltip', widget, data, placement );
				}
				else if( inspectedItem.GetEquipmentArea() == gamedataEquipmentArea.SystemReplacementCW )
				{
					m_TooltipsManager.ShowTooltipAtWidget( 'cyberdeckTooltip', widget, data, placement );
				}
				else
				{
					m_TooltipsManager.ShowTooltipAtWidget( itemTooltips[ 0 ], widget, data, placement );
				}
			}
		}
	}

	protected event OnInventoryItemHoverOut( evt : ItemDisplayHoverOutEvent )
	{
		m_TooltipsManager.HideTooltips();
		m_buttonHintsController.RemoveButtonHint( 'select' );
		m_buttonHintsController.RemoveButtonHint( 'preview_item' );
		m_buttonHintsController.RemoveButtonHint( 'favourite_item' );
		m_lastItemHoverOverEvent = NULL;
		m_pressedItemDisplay = NULL;
	}

}

class VendorDataView extends BackpackDataView
{
	protected var m_isVendorGrid : Bool;
	protected var m_openTime : GameTime;

	public function SetVendorGrid( value : Bool )
	{
		m_isVendorGrid = value;
	}

	public function SetOpenTime( time : GameTime )
	{
		m_openTime = time;
	}

	protected override function PreSortingInjection( builder : ItemCompareBuilder ) : ItemCompareBuilder
	{
		return builder.QuestItem();
	}

	public override function DerivedFilterItem( data : IScriptable ) : DerivedFilterResult
	{
		var m_wrappedData : VendorUIInventoryItemData;
		m_wrappedData = ( ( VendorUIInventoryItemData )( ( ( IScriptable )( data ) ) ) );
		if( !( m_wrappedData ) )
		{
			return DerivedFilterResult.Pass;
		}
		if( m_itemFilterType == ItemFilterCategory.Buyback )
		{
			return ( ( m_wrappedData.IsBuybackStack ) ? ( DerivedFilterResult.True ) : ( DerivedFilterResult.False ) );
		}
		else if( m_itemFilterType == ItemFilterCategory.NewWardrobeAppearances )
		{
			return ( ( m_wrappedData.IsNotInWardrobe ) ? ( DerivedFilterResult.True ) : ( DerivedFilterResult.False ) );
		}
		else
		{
			return ( ( m_wrappedData.IsBuybackStack ) ? ( DerivedFilterResult.False ) : ( DerivedFilterResult.Pass ) );
		}
	}

}

class VendorItemVirtualController extends inkVirtualCompoundItemController
{
	var m_data : VendorInventoryItemData;
	var m_newData : VendorUIInventoryItemData;
	var m_itemViewController : weak< InventoryItemDisplayController >;
	var m_isSpawnInProgress : Bool;

	protected event OnInitialize()
	{
		RegisterToCallback( 'OnSelected', this, 'OnSelected' );
	}

	public function OnDataChanged( value : Variant )
	{
		var displayToCreate : CName;
		m_newData = ( ( VendorUIInventoryItemData )( ( ( IScriptable )value ) ) );
		displayToCreate = 'itemDisplay';
		if( m_newData )
		{
			if( m_newData.Item.IsWeapon() )
			{
				displayToCreate = 'weaponDisplay';
			}
		}
		else
		{
			m_data = ( ( VendorInventoryItemData )( ( ( IScriptable )value ) ) );
			if( InventoryItemData.GetEquipmentArea( m_data.ItemData ) == gamedataEquipmentArea.Weapon )
			{
				displayToCreate = 'weaponDisplay';
			}
		}
		if( !( m_isSpawnInProgress ) )
		{
			if( !( m_itemViewController ) )
			{
				m_isSpawnInProgress = true;
				ItemDisplayUtils.AsyncSpawnCommonSlotController( this, this.GetRootWidget(), displayToCreate, 'OnSpawned' );
			}
			else
			{
				UpdateControllerData();
			}
		}
	}

	protected event OnSpawned( widget : inkWidget, userData : IScriptable )
	{
		m_isSpawnInProgress = false;
		m_itemViewController = ( ( InventoryItemDisplayController )( widget.GetController() ) );
		UpdateControllerData();
	}

	private function UpdateControllerData()
	{
		var applyDLCAddedIndicator : Bool;
		if( m_newData )
		{
			if( m_newData.IsVendorItem )
			{
				m_itemViewController.Setup( m_newData.Item, m_newData.DisplayContextData, m_newData.IsEnoughMoney, false, false, m_newData.OverrideQuantity );
				applyDLCAddedIndicator = m_newData.Item.GetItemData().HasTag( 'DLCAdded' ) && m_data.IsDLCAddedActiveItem;
				m_itemViewController.SetDLCNewIndicator( applyDLCAddedIndicator );
			}
			else
			{
				m_itemViewController.Setup( m_newData.Item, m_newData.DisplayContextData );
				m_itemViewController.SetQuestBought( m_newData.IsQuestBought );
			}
			m_itemViewController.SetComparisonState( m_newData.ComparisonState );
			m_itemViewController.SetBuybackStack( m_newData.IsBuybackStack );
			m_itemViewController.SetIsPlayerFavourite( m_newData.Item.IsPlayerFavourite() );
			return;
		}
		if( m_data.IsVendorItem )
		{
			m_itemViewController.Setup( m_data.ItemData, ItemDisplayContext.Vendor, m_data.IsEnoughMoney );
			applyDLCAddedIndicator = InventoryItemData.GetGameItemData( m_data.ItemData ).HasTag( 'DLCAdded' ) && m_data.IsDLCAddedActiveItem;
			m_itemViewController.SetDLCNewIndicator( applyDLCAddedIndicator );
		}
		else
		{
			m_itemViewController.Setup( m_data.ItemData, ItemDisplayContext.VendorPlayer );
		}
		m_itemViewController.SetComparisonState( m_data.ComparisonState );
		m_itemViewController.SetBuybackStack( m_data.IsBuybackStack );
		m_itemViewController.SetIsPlayerFavourite( m_data.Item.IsPlayerFavourite() );
	}

	protected event OnSelected( itemController : weak< inkVirtualCompoundItemController >, discreteNav : Bool )
	{
		var widget : weak< inkWidget >;
		if( discreteNav )
		{
			widget = GetRootWidget();
			SetCursorOverWidget( widget );
		}
	}

}

class VendorUIInventoryItemData extends WrappedInventoryItemData
{
	var ItemPrice : Float;
	var IsVendorItem : Bool;
	var IsBuybackStack : Bool;
	var IsEnoughMoney : Bool;
	var IsDLCAddedActiveItem : Bool;
	var IsNotInWardrobe : Bool;
}

class VendorInventoryItemData extends WrappedInventoryItemData
{
	var IsVendorItem : Bool;
	var IsEnoughMoney : Bool;
	var IsBuybackStack : Bool;
	var IsDLCAddedActiveItem : Bool;
}

class VendorJunkSellItem
{
	var item : weak< gameItemData >;
	var quantity : Int32;
}

class SoldItem
{
	var itemID : ItemID;
	var quantity : Int32;
	var piecePrice : Int32;
}

class SoldItemsCache
{
	private var m_cache : array< SoldItem >;

	public function AddItem( itemID : ItemID, quantity : Int32, piecePrice : Int32 )
	{
		var item : SoldItem;
		item = new SoldItem;
		item.itemID = itemID;
		item.quantity = quantity;
		item.piecePrice = piecePrice;
		AddItem( item );
	}

	public function AddItem( item : SoldItem )
	{
		var i, limit : Int32;
		for( i = 0, limit = m_cache.Size(); i < limit; i += 1 )
		{
			if( m_cache[ i ].itemID == item.itemID )
			{
				m_cache[ i ].quantity += item.quantity;
				return;
			}
		}
		m_cache.PushBack( item );
	}

	public function RemoveItem( itemID : ItemID, quantity : Int32 )
	{
		var i : Int32;
		for( i = 0; i < m_cache.Size(); i += 1 )
		{
			if( m_cache[ i ].itemID == itemID )
			{
				if( m_cache[ i ].quantity > quantity )
				{
					m_cache[ i ].quantity -= quantity;
				}
				else
				{
					m_cache.Erase( i );
				}
				break;
			}
		}
	}

	public function GetItem( itemID : ItemID ) : SoldItem
	{
		var i : Int32;
		for( i = 0; i < m_cache.Size(); i += 1 )
		{
			if( m_cache[ i ].itemID == itemID )
			{
				return m_cache[ i ];
			}
		}
		return NULL;
	}

	public function GetItemPrice( itemID : ItemID ) : Int32
	{
		var i : Int32;
		for( i = 0; i < m_cache.Size(); i += 1 )
		{
			if( m_cache[ i ].itemID == itemID )
			{
				return m_cache[ i ].piecePrice;
			}
		}
		return 0;
	}

}

class UIVendorAttachedEvent extends Event
{
	var vendorID : TweakDBID;
	var vendorObject : weak< GameObject >;
}

class UIVendorItemsSoldEvent extends Event
{
	var requestID : Int32;
	var itemsID : array< ItemID >;
	var quantity : array< Int32 >;
	var piecesPrice : array< Int32 >;
}

class UIVendorItemsBoughtEvent extends Event
{
	var requestID : Int32;
	var itemsID : array< ItemID >;
	var quantity : array< Int32 >;
}

class VenodrRequestQueueEntry
{
	var requestID : Int32;
	var itemID : ItemID;
}

class RefreshSellQueueEvent extends Event
{
}

class RefreshBuyQueueEvent extends Event
{
}

