class CraftingMainLogicController extends inkLogicController
{
	private const var TIME_UNTIL_SELECTION : Float;
	default TIME_UNTIL_SELECTION = 0.3f;
	protected editable var m_root : inkWidgetRef;
	protected editable var m_itemDetailsContainer : inkWidgetRef;
	protected editable var m_leftListScrollHolder : inkWidgetRef;
	protected editable var m_virtualListContainer : inkVirtualCompoundRef;
	protected editable var m_filterGroup : inkWidgetRef;
	protected editable var m_sortingButton : inkWidgetRef;
	protected editable var m_sortingDropdown : inkWidgetRef;
	protected editable var m_tooltipContainer : inkWidgetRef;
	protected editable var m_itemName : inkTextRef;
	protected editable var m_itemQuality : inkTextRef;
	protected editable var m_progressBarContainer : inkCompoundRef;
	protected editable var m_progressButtonContainer : inkCompoundRef;
	protected editable var m_blockedText : inkTextRef;
	protected editable var m_ingredientsListContainer : inkCompoundRef;
	protected var m_notificationType : UIMenuNotificationType;
	protected var m_classifier : CraftingItemTemplateClassifier;
	protected var m_dataView : CraftingDataView;
	protected var m_dataSource : ScriptableDataSource;
	protected var m_virtualListController : weak< inkVirtualGridController >;
	protected var m_leftListScrollController : weak< inkScrollController >;
	protected var m_ingredientsControllerList : array< weak< IngredientListItemLogicController > >;
	protected var m_maxIngredientCount : Int32;
	protected var m_selectedRecipe : RecipeData;
	protected var m_selectedItemData : InventoryItemData;
	protected var m_isCraftable : Bool;
	protected var m_filters : array< Int32 >;
	protected var m_progressButtonController : weak< ProgressBarButton >;
	protected var m_itemWeaponController : weak< InventoryItemDisplayController >;
	protected var m_itemIngredientController : weak< InventoryItemDisplayController >;
	protected var m_doPlayFilterSounds : Bool;
	protected var m_craftingGameController : weak< CraftingMainGameController >;
	protected var m_craftingSystem : weak< CraftingSystem >;
	protected var m_tooltipsManager : weak< gameuiTooltipsManager >;
	protected var m_buttonHintsController : weak< ButtonHints >;
	protected var m_inventoryManager : weak< InventoryDataManagerV2 >;
	protected var m_sortingController : weak< DropdownListController >;
	protected var m_sortingButtonController : weak< DropdownButtonController >;
	protected var m_isPanelOpen : Bool;
	protected var m_hasSpawnedTooltip : Bool;
	private var m_currentSelected : weak< CraftableItemLogicController >;
	private var m_itemTooltipPath : ResRef;
	private var m_isProcessing : Bool;
	protected var m_DelaySystem : weak< DelaySystem >;
	protected var m_StatsSystem : weak< StatsSystem >;
	protected var m_Player : weak< PlayerPuppet >;
	protected var m_Game : GameInstance;
	private var m_firstClicked : Bool;
	private var m_progress : Float;
	private var m_isFirstOpen : Bool;
	default m_isFirstOpen = true;

	public virtual function Init( craftingGameController : weak< CraftingMainGameController > )
	{
		m_craftingGameController = craftingGameController;
		m_craftingSystem = craftingGameController.GetCraftingSystem();
		m_tooltipsManager = craftingGameController.GetTooltipManager();
		m_buttonHintsController = craftingGameController.GetButtonHintsController();
		m_inventoryManager = craftingGameController.GetInventoryManager();
		InitVirtualList();
		SetupIngredientWidgets();
		SetupFilters();
		SetupSortingDropdown();
		inkWidgetRef.SetVisible( m_itemDetailsContainer, false );
		m_leftListScrollController = ( ( inkScrollController )( inkWidgetRef.GetController( m_leftListScrollHolder ) ) );
		m_itemTooltipPath = R"base\gameplay\gui\common\tooltip\new_itemtooltip.inkwidget";
		m_Player = m_craftingGameController.GetPlayer();
		m_Game = m_Player.GetGame();
		m_DelaySystem = GameInstance.GetDelaySystem( m_Game );
		m_StatsSystem = GameInstance.GetStatsSystem( m_Game );
	}

	protected function InitVirtualList()
	{
		m_virtualListController = ( ( inkVirtualGridController )( inkVirtualCompoundRef.GetControllerByType( m_virtualListContainer, 'inkVirtualGridController' ) ) );
		m_classifier = new CraftingItemTemplateClassifier;
		m_virtualListController.SetClassifier( m_classifier );
		m_dataSource = new ScriptableDataSource;
		m_dataView = new CraftingDataView;
		m_dataView.SetSource( m_dataSource );
		m_dataView.EnableSorting();
		m_dataView.BindUIScriptableSystem( m_craftingGameController.GetScriptableSystem() );
		m_virtualListController.SetSource( m_dataView );
		m_virtualListController.RegisterToCallback( 'OnItemSelected', this, 'OnItemSelect' );
	}

	public function OpenPanel()
	{
		var currentIndex : Uint32;
		inkWidgetRef.SetVisible( m_root, true );
		RefreshListViewContent();
		SetItemButtonHintsHoverOut( NULL );
		if( !( m_isFirstOpen ) )
		{
			currentIndex = m_virtualListController.GetToggledIndex();
			DispatchSelectDelayed( currentIndex );
		}
		else
		{
			currentIndex = 0;
			DispatchSelectDelayed( currentIndex );
			m_isFirstOpen = false;
		}
		m_isPanelOpen = true;
	}

	public virtual function RefreshListViewContent( optional inventoryItemData : InventoryItemData ) {}

	public virtual function OnChangeTab( isCurrent : Bool )
	{
		if( !( isCurrent ) )
		{
			m_currentSelected = NULL;
		}
	}

	public function ClosePanel()
	{
		inkWidgetRef.SetVisible( m_root, false );
		m_dataSource.Clear();
		m_isPanelOpen = false;
	}

	protected virtual function SetupIngredientWidgets()
	{
		var i : Int32;
		if( m_ingredientsControllerList.Size() < m_maxIngredientCount )
		{
			for( i = 0; i < m_maxIngredientCount; i += 1 )
			{
				AsyncSpawnFromLocal( inkCompoundRef.Get( m_ingredientsListContainer ), 'ingredientsListItem', this, 'OnIngedientControllerSpawned' );
			}
		}
	}

	protected event OnIngedientControllerSpawned( widget : inkWidget, userData : IScriptable )
	{
		var controller : weak< IngredientListItemLogicController >;
		controller = ( ( IngredientListItemLogicController )( widget.GetController() ) );
		controller.SetUnusedState();
		m_ingredientsControllerList.PushBack( controller );
	}

	protected virtual function SetupFilters()
	{
		var radioGroup : FilterRadioGroup;
		radioGroup = ( ( FilterRadioGroup )( inkWidgetRef.GetControllerByType( m_filterGroup, 'FilterRadioGroup' ) ) );
		radioGroup.SetData( m_filters, m_tooltipsManager, 0 );
		radioGroup.RegisterToCallback( 'OnValueChanged', this, 'OnFilterChange' );
		radioGroup.Toggle( 0 );
		OnFilterChange( NULL, 0 );
	}

	protected event OnFilterChange( controller : weak< inkRadioGroupController >, selectedIndex : Int32 )
	{
		var filter : ItemFilterCategory;
		filter = ( ( ItemFilterCategory )( m_filters[ selectedIndex ] ) );
		m_dataView.SetFilterType( filter );
		PlayLibraryAnimation( 'player_grid_show' );
		m_leftListScrollController.SetScrollPosition( 0.0 );
		if( m_doPlayFilterSounds )
		{
			PlaySound( 'Button', 'OnPress' );
		}
		inkWidgetRef.SetVisible( m_itemDetailsContainer, false );
	}

	protected function SetupSortingDropdown()
	{
		inkWidgetRef.RegisterToCallback( m_sortingButton, 'OnRelease', this, 'OnSortingButtonClicked' );
		m_sortingController = ( ( DropdownListController )( inkWidgetRef.GetController( m_sortingDropdown ) ) );
		m_sortingButtonController = ( ( DropdownButtonController )( inkWidgetRef.GetController( m_sortingButton ) ) );
		m_sortingController.Setup( this, SortingDropdownData.GetDefaultDropdownOptions(), m_sortingButtonController );
		m_sortingButtonController.SetData( GetDropdownOption( ItemSortMode.Default ) );
	}

	protected event OnSortingButtonClicked( evt : inkPointerEvent )
	{
		if( evt.IsAction( 'click' ) )
		{
			m_sortingController.Toggle();
			PlaySound( 'Button', 'OnPress' );
		}
	}

	protected event OnDropdownItemClickedEvent( evt : DropdownItemClickedEvent )
	{
		var identifier : ItemSortMode;
		var data : DropdownItemData;
		identifier = ( ( ItemSortMode )evt.identifier );
		data = GetDropdownOption( identifier );
		if( data )
		{
			m_sortingButtonController.SetData( data );
			m_dataView.SetSortMode( identifier );
			PlaySound( 'Button', 'OnPress' );
		}
	}

	protected function SetCraftingButton( const label : ref< String > )
	{
		m_progressButtonController = ( ( ProgressBarButton )( inkCompoundRef.GetControllerByType( m_progressButtonContainer, 'ProgressBarButton' ) ) );
		m_progressButtonController.SetupProgressButton( label, ( ( ProgressBarsController )( inkCompoundRef.GetControllerByType( m_progressBarContainer, 'ProgressBarsController' ) ) ) );
		m_progressButtonController.ButtonController.RegisterToCallback( 'OnPress', this, 'OnButtonClick' );
		m_progressButtonController.ButtonController.RegisterToCallback( 'OnHoverOver', this, 'SetItemButtonHintsHoverOver' );
		m_progressButtonController.ButtonController.RegisterToCallback( 'OnHoverOut', this, 'SetItemButtonHintsHoverOut' );
		inkCompoundRef.SetVisible( m_progressBarContainer, false );
	}

	protected event OnButtonClick( evt : inkPointerEvent )
	{
		var craftingNotification : UIMenuNotificationEvent;
		if( evt.IsAction( 'craft_item' ) )
		{
			if( !( m_isCraftable ) )
			{
				if( m_notificationType != UIMenuNotificationType.CraftingNoPerks )
				{
					craftingNotification = new UIMenuNotificationEvent;
					craftingNotification.m_notificationType = m_notificationType;
					QueueEvent( craftingNotification );
				}
			}
			else
			{
				StartProcess();
			}
		}
		m_craftingGameController.DisableTabs();
	}

	protected event OnItemSelect( previous : inkVirtualCompoundItemController, next : inkVirtualCompoundItemController )
	{
		if( next == m_currentSelected )
		{
			return true;
		}
		UpdateSelection( ( ( CraftableItemLogicController )( next ) ) );
		ResetProcess();
		SetItemButtonHintsHoverOver( NULL );
	}

	private function UpdateSelection( selection : CraftableItemLogicController )
	{
		if( m_currentSelected )
		{
			m_currentSelected.UnregisterFromCallback( 'OnPress', this, 'OnPressSelectedItem' );
			m_currentSelected.UnregisterFromCallback( 'OnHold', this, 'OnHoldSelectedItem' );
			m_currentSelected.UnregisterFromCallback( 'OnHoverOut', this, 'OnHoverOutSelectedItem' );
			m_currentSelected.UnregisterFromCallback( 'OnRelease', this, 'OnReleaseSelectedItem' );
			m_firstClicked = false;
		}
		m_currentSelected = selection;
		m_currentSelected.RegisterToCallback( 'OnPress', this, 'OnPressSelectedItem' );
		m_currentSelected.RegisterToCallback( 'OnHold', this, 'OnHoldSelectedItem' );
		m_currentSelected.RegisterToCallback( 'OnHoverOut', this, 'OnHoverOutSelectedItem' );
		m_currentSelected.RegisterToCallback( 'OnRelease', this, 'OnReleaseSelectedItem' );
	}

	private function OnPressSelectedItem( evt : inkPointerEvent )
	{
		if( evt.IsAction( 'craft_item' ) )
		{
			UpdateItemPreview( m_currentSelected );
			PlaySound( 'Button', 'OnPress' );
			if( m_isCraftable )
			{
				StartProcess();
				m_craftingGameController.DisableTabs();
			}
		}
		else if( evt.IsAction( 'click' ) && !( evt.IsAction( 'mouse_left' ) ) )
		{
			UpdateItemPreview( m_currentSelected );
			PlaySound( 'Button', 'OnPress' );
		}
	}

	protected event OnHoverOutSelectedItem( evt : inkPointerEvent )
	{
		m_progressButtonController.Lock();
		if( m_firstClicked )
		{
			PlaySound( 'Item', 'OnCraftFailed' );
		}
		if( m_isProcessing )
		{
			m_craftingGameController.EnableTabs();
		}
		ResetProcess();
	}

	protected event OnHoldSelectedItem( evt : inkPointerEvent )
	{
		m_progress = evt.GetHoldProgress();
		if( evt.IsAction( 'craft_item' ) )
		{
			if( ( m_progress > 0.2 ) && m_isProcessing )
			{
				m_progressButtonController.UpdateCraftProcess( evt );
				if( m_isCraftable && !( m_firstClicked ) )
				{
					m_firstClicked = true;
					PlaySound( 'Item', 'OnCraftStarted' );
				}
			}
		}
	}

	protected event OnReleaseSelectedItem( evt : inkPointerEvent )
	{
		if( evt.IsAction( 'craft_item' ) )
		{
			m_craftingGameController.EnableTabs();
			ResetProcess();
			if( m_firstClicked )
			{
				m_firstClicked = false;
				PlaySound( 'Item', 'OnCraftFailed' );
			}
		}
	}

	protected virtual function UpdateItemPreview( craftableController : CraftableItemLogicController ) {}

	protected event OnUninitialize()
	{
		m_virtualListController.SetSource( NULL );
		m_virtualListController.SetClassifier( NULL );
		m_dataView.SetSource( NULL );
		m_dataView = NULL;
		m_dataSource = NULL;
		m_classifier = NULL;
		if( m_currentSelected )
		{
			m_currentSelected.UnregisterFromCallback( 'OnPress', this, 'OnPressSelectedItem' );
			m_currentSelected.UnregisterFromCallback( 'OnHold', this, 'OnHoldSelectedItem' );
			m_currentSelected.UnregisterFromCallback( 'OnHoverOut', this, 'OnHoverOutSelectedItem' );
			m_currentSelected.UnregisterFromCallback( 'OnRelease', this, 'OnReleaseSelectedItem' );
		}
		m_virtualListController.UnregisterFromCallback( 'OnItemSelected', this, 'OnItemSelect' );
		m_progressButtonController.ButtonController.UnregisterFromCallback( 'OnPress', this, 'OnButtonClick' );
		m_progressButtonController.ButtonController.UnregisterFromCallback( 'OnHoverOver', this, 'SetItemButtonHintsHoverOver' );
		m_progressButtonController.ButtonController.UnregisterFromCallback( 'OnHoverOut', this, 'SetItemButtonHintsHoverOut' );
		m_doPlayFilterSounds = false;
		if( m_firstClicked )
		{
			PlaySound( 'Item', 'OnCraftFailed' );
		}
	}

	protected function SpawnItemTooltipAsync( parentWidget : weak< inkWidget >, optional callbackObject : IScriptable, optional callbackFunctionName : CName )
	{
		AsyncSpawnFromExternal( parentWidget, m_itemTooltipPath, 'itemTooltip', callbackObject, callbackFunctionName );
	}

	protected virtual function SetItemButtonHintsHoverOver( evt : inkPointerEvent ) {}

	protected function SetItemButtonHintsHoverOut( evt : inkPointerEvent )
	{
		m_buttonHintsController.RemoveButtonHint( 'craft_item' );
		m_craftingGameController.EnableTabs();
		ResetProcess();
	}

	public static function IsWeapon( type : gamedataEquipmentArea ) : Bool
	{
		return ( ( type == gamedataEquipmentArea.Weapon || type == gamedataEquipmentArea.WeaponHeavy ) || type == gamedataEquipmentArea.WeaponWheel ) || type == gamedataEquipmentArea.WeaponLeft;
	}

	public static function GetDropdownOption( identifier : ItemSortMode ) : DropdownItemData
	{
		var options : array< DropdownItemData >;
		var i : Int32;
		options = SortingDropdownData.GetDefaultDropdownOptions();
		for( i = 0; i < options.Size(); i += 1 )
		{
			if( ( ( ItemSortMode )options[ i ].identifier ) == identifier )
			{
				return options[ i ];
			}
		}
		return NULL;
	}

	private function ResetProcess()
	{
		m_progressButtonController.Reset();
		m_isProcessing = false;
	}

	private function StartProcess()
	{
		if( m_isProcessing )
		{
			return;
		}
		m_isProcessing = true;
		m_progressButtonController.Unlock();
		m_progressButtonController.Start();
	}

	protected function DispatchSelectDelayed( index : Uint32 )
	{
		var delayedSelect : DelayedSelect;
		delayedSelect = new DelayedSelect;
		delayedSelect.m_controller = this;
		delayedSelect.m_index = index;
		m_DelaySystem.DelayCallback( delayedSelect, TIME_UNTIL_SELECTION, false );
	}

	public function Select( index : Uint32 )
	{
		m_virtualListController.ToggleItem( index );
		m_virtualListController.SelectItem( index );
		m_virtualListController.ScrollToIndex( index );
		UpdateItemPreview( ( ( CraftableItemLogicController )( m_virtualListController.GetToggledItem() ) ) );
	}

	protected function IsEmptyData() : Bool
	{
		return m_dataSource.Size() < 1;
	}

}

class DelayedSelect extends DelayCallback
{
	var m_controller : weak< CraftingMainLogicController >;
	var m_index : Uint32;

	public override function Call()
	{
		if( m_controller )
		{
			m_controller.Select( m_index );
		}
	}

}

