class ItemInSlotPrereqState extends PrereqState
{
	var m_listener : ItemInSlotCallback;
	var m_owner : weak< GameObject >;

	public function SlotFilled( slotID : TweakDBID, itemID : ItemID )
	{
		const var prereq : ItemInSlotPrereq;
		var checkPassed : Bool;
		prereq = ( ( ItemInSlotPrereq )( GetPrereq() ) );
		if( slotID == prereq.m_slotID )
		{
			checkPassed = prereq.Evaluate( itemID, m_owner );
			OnChanged( checkPassed );
		}
	}

	public function SlotEmptied( slotID : TweakDBID, itemID : ItemID )
	{
		const var prereq : ItemInSlotPrereq;
		prereq = ( ( ItemInSlotPrereq )( GetPrereq() ) );
		if( slotID == prereq.m_slotID )
		{
			OnChanged( false );
		}
	}

}

class ItemInSlotPrereq extends IScriptablePrereq
{
	var m_slotID : TweakDBID;
	var m_slotCheckType : gamedataCheckType;
	var m_itemType : gamedataItemType;
	var m_itemCategory : gamedataItemCategory;
	var m_weaponEvolution : gamedataWeaponEvolution;
	var m_itemTag : CName;
	var m_invert : Bool;
	var m_skipOnApply : Bool;
	var m_waitForVisuals : Bool;

	protected export const override function OnRegister( state : PrereqState, game : GameInstance, context : IScriptable ) : Bool
	{
		var owner : GameObject;
		var castedState : ItemInSlotPrereqState;
		owner = ( ( GameObject )( context ) );
		castedState = ( ( ItemInSlotPrereqState )( state ) );
		castedState.m_listener = new ItemInSlotCallback;
		castedState.m_listener.m_waitForVisuals = m_waitForVisuals;
		castedState.m_listener.slotID = m_slotID;
		castedState.m_owner = owner;
		castedState.m_listener.RegisterState( castedState );
		GameInstance.GetTransactionSystem( game ).RegisterAttachmentSlotListener( owner, castedState.m_listener );
		return false;
	}

	protected export const override function OnUnregister( state : PrereqState, game : GameInstance, context : IScriptable )
	{
		var castedState : StatPrereqState;
		castedState = ( ( StatPrereqState )( state ) );
		if( castedState )
		{
			castedState.m_listener = NULL;
		}
	}

	protected export const override function OnApplied( state : PrereqState, game : GameInstance, context : IScriptable )
	{
		var owner : weak< GameObject >;
		var castedState : ItemInSlotPrereqState;
		var itemObj : weak< ItemObject >;
		castedState = ( ( ItemInSlotPrereqState )( state ) );
		owner = ( ( GameObject )( context ) );
		if( m_skipOnApply )
		{
			return;
		}
		itemObj = GameInstance.GetTransactionSystem( owner.GetGame() ).GetItemInSlot( owner, m_slotID );
		if( itemObj )
		{
			castedState.SlotFilled( m_slotID, itemObj.GetItemID() );
		}
	}

	public export const override function IsFulfilled( game : GameInstance, context : IScriptable ) : Bool
	{
		var itemObj : weak< ItemObject >;
		var owner : weak< GameObject >;
		owner = ( ( GameObject )( context ) );
		if( m_skipOnApply )
		{
			return false;
		}
		itemObj = GameInstance.GetTransactionSystem( owner.GetGame() ).GetItemInSlot( owner, m_slotID );
		if( itemObj )
		{
			return Evaluate( itemObj.GetItemID(), owner );
		}
		else
		{
			return false;
		}
	}

	protected export override function Initialize( recordID : TweakDBID )
	{
		m_slotCheckType = TweakDBInterface.GetCheckTypeRecord( TweakDBInterface.GetForeignKeyDefault( recordID + T".checkType" ) ).Type();
		m_slotID = TweakDBInterface.GetAttachmentSlotRecord( TweakDBInterface.GetForeignKeyDefault( recordID + T".attachmentSlot" ) ).GetID();
		m_itemType = TweakDBInterface.GetItemTypeRecord( TweakDBInterface.GetForeignKeyDefault( recordID + T".itemType" ) ).Type();
		m_itemCategory = TweakDBInterface.GetItemCategoryRecord( TweakDBInterface.GetForeignKeyDefault( recordID + T".itemCategory" ) ).Type();
		m_weaponEvolution = TweakDBInterface.GetWeaponEvolutionRecord( TweakDBInterface.GetForeignKeyDefault( recordID + T".weaponEvolution" ) ).Type();
		m_itemTag = TweakDBInterface.GetCName( recordID + T".itemTag", '' );
		m_invert = TweakDBInterface.GetBool( recordID + T".inverted", false );
		m_skipOnApply = TweakDBInterface.GetBool( recordID + T".skipOnApply", false );
		m_waitForVisuals = TweakDBInterface.GetBool( recordID + T".waitForVisuals", false );
	}

	public const function Evaluate( itemID : ItemID, owner : weak< GameObject > ) : Bool
	{
		var result : Bool;
		switch( m_slotCheckType )
		{
			case gamedataCheckType.None:
				result = false;
			break;
			case gamedataCheckType.Tag:
				result = Evaluate( itemID, m_itemTag );
			break;
			case gamedataCheckType.Type:
				result = Evaluate( RPGManager.GetItemType( itemID ) );
			break;
			case gamedataCheckType.Category:
				result = Evaluate( RPGManager.GetItemCategory( itemID ) );
			break;
			case gamedataCheckType.Evolution:
				result = Evaluate( RPGManager.GetWeaponEvolution( itemID ) );
			break;
			case gamedataCheckType.FullyModded:
				result = CheckGenericWeaponModSlots( itemID, owner );
			break;
			default:
				result = false;
			break;
		}
		return ( ( m_invert ) ? ( !( result ) ) : ( result ) );
	}

	public const function Evaluate( itemCategory : gamedataItemCategory ) : Bool
	{
		return itemCategory == m_itemCategory;
	}

	public const function Evaluate( itemType : gamedataItemType ) : Bool
	{
		return itemType == m_itemType;
	}

	public const function Evaluate( weaponEvolution : gamedataWeaponEvolution ) : Bool
	{
		return weaponEvolution == m_weaponEvolution;
	}

	public const function Evaluate( itemID : ItemID, tag : CName ) : Bool
	{
		var tags : array< CName >;
		tags = RPGManager.GetItemRecord( itemID ).Tags();
		return tags.Contains( tag );
	}

	public const function CheckGenericWeaponModSlots( itemID : ItemID, owner : weak< GameObject > ) : Bool
	{
		var attachmentSlotList : array< TweakDBID >;
		var quality : Float;
		var index : Int32;
		GameInstance.GetTransactionSystem( owner.GetGame() ).GetEmptySlotsOnItem( owner, itemID, attachmentSlotList );
		quality = GameInstance.GetTransactionSystem( owner.GetGame() ).GetItemData( owner, itemID ).GetStatValueByType( gamedataStatType.Quality );
		for( index = 0; ( index < attachmentSlotList.Size() ) && ( index < 4 ); index += 1 )
		{
			if( IsGenericWeaponMod( attachmentSlotList[ index ], ( ( Int32 )( quality ) ) ) )
			{
				return false;
			}
		}
		return true;
	}

	public const function IsGenericWeaponMod( tweakDBID : TweakDBID, quality : Int32 ) : Bool
	{
		var index : Int32;
		var weaponModSlotIDs : TweakDBID[ 4 ];
		weaponModSlotIDs[ 0 ] = T"AttachmentSlots.Power_AR_SMG_LMG_WeaponMod1";
		weaponModSlotIDs[ 1 ] = T"AttachmentSlots.Power_AR_SMG_LMG_WeaponMod2";
		weaponModSlotIDs[ 2 ] = T"AttachmentSlots.Tech_AR_SMG_LMG_WeaponMod1";
		weaponModSlotIDs[ 3 ] = T"AttachmentSlots.Tech_AR_SMG_LMG_WeaponMod2";
		for( index = 0; index < quality; index = index + 1 )
		{
			if( tweakDBID == weaponModSlotIDs[ index ] )
			{
				return true;
			}
		}
		return false;
	}

}

class ItemInSlotCallback extends AttachmentSlotsScriptCallback
{
	protected var m_state : weak< ItemInSlotPrereqState >;
	var m_waitForVisuals : Bool;

	public export override function OnItemEquipped( slot : TweakDBID, item : ItemID )
	{
		if( !( m_waitForVisuals ) )
		{
			m_state.SlotFilled( slot, item );
		}
	}

	public export override function OnItemEquippedVisual( slot : TweakDBID, item : ItemID )
	{
		if( m_waitForVisuals )
		{
			m_state.SlotFilled( slot, item );
		}
	}

	public export override function OnItemUnequipped( slot : TweakDBID, item : ItemID )
	{
		m_state.SlotEmptied( slot, item );
	}

	public function RegisterState( state : PrereqState )
	{
		m_state = ( ( ItemInSlotPrereqState )( state ) );
	}

}

