enum EDeviceChallengeSkill
{
	Invalid = 0,
	Hacking = 1,
	Engineering = 2,
	Athletics = 3,
}

enum EDeviceChallengeAttribute
{
	Invalid = 0,
	Strength = 1,
	Reflexes = 2,
	Intelligence = 3,
	TechnicalAbility = 4,
	Cool = 5,
}

abstract class GameplayConditionBase extends IScriptable
{
	protected var m_entityID : EntityID;

	public virtual function Evaluate( requester : GameObject ) : Bool
	{
		return false;
	}

	public virtual function GetDescription( requester : GameObject ) : Condition
	{
		var empty : Condition;
		return empty;
	}

	protected function GetPlayer( requester : GameObject ) : GameObject
	{
		return GameInstance.GetPlayerSystem( requester.GetGame() ).GetLocalPlayerMainGameObject();
	}

	public function SetEntityID( id : EntityID )
	{
		m_entityID = id;
	}

}

class GameplaySkillCondition extends GameplayConditionBase
{
	[ customEditor = "TweakDBGroupInheritance;BaseStats.SkillStat" ]
	protected instanceeditable persistent var m_skillToCheck : TweakDBID;
	private instanceeditable persistent var m_difficulty : EGameplayChallengeLevel;
	private persistent var m_skillBonus : TweakDBID;
	private persistent var m_requiredLevel : Int32;

	public override function Evaluate( requester : GameObject ) : Bool
	{
		if( GetPlayerSkill( requester ) >= GetRequiredLevel( requester.GetGame() ) )
		{
			return true;
		}
		else
		{
			return false;
		}
	}

	public function GetRequiredLevel( gi : GameInstance ) : Int32
	{
		if( IsRequiredLevelSetup() )
		{
			return m_requiredLevel;
		}
		return RPGManager.CheckDifficultyToStatValue( gi, GetStatType(), m_difficulty, m_entityID );
	}

	public function TrySetRequiredLevel( requiredLevel : Int32 )
	{
		if( !( IsRequiredLevelSetup() ) )
		{
			m_requiredLevel = requiredLevel;
		}
	}

	private function IsRequiredLevelSetup() : Bool
	{
		return m_requiredLevel >= 0;
	}

	public function GetPlayerSkill( requester : GameObject ) : Int32
	{
		var statsSystem : StatsSystem;
		var playerEntity : EntityID;
		var skillValue : Int32;
		statsSystem = GameInstance.GetStatsSystem( requester.GetGame() );
		playerEntity = GameInstance.GetPlayerSystem( requester.GetGame() ).GetLocalPlayerControlledGameObject().GetEntityID();
		skillValue = ( ( Int32 )( statsSystem.GetStatValue( playerEntity, GetStatType() ) ) );
		skillValue += ( ( Int32 )( statsSystem.GetStatValue( playerEntity, GetStatBonusType() ) ) );
		return skillValue;
	}

	private function GetStatType() : gamedataStatType
	{
		return TweakDBInterface.GetStatRecord( m_skillToCheck ).StatType();
	}

	private function GetStatBonusType() : gamedataStatType
	{
		return TweakDBInterface.GetStatRecord( m_skillBonus ).StatType();
	}

	public function SetProperties( sel_skill : EDeviceChallengeSkill, sel_difficulty : EGameplayChallengeLevel )
	{
		var skillString : String;
		m_difficulty = sel_difficulty;
		if( sel_skill == EDeviceChallengeSkill.Hacking )
		{
			skillString = "Intelligence";
		}
		else if( sel_skill == EDeviceChallengeSkill.Engineering )
		{
			skillString = "TechnicalAbility";
		}
		else if( sel_skill == EDeviceChallengeSkill.Athletics )
		{
			skillString = "Strength";
		}
		m_skillToCheck = TDBID.Create( "BaseStats." + skillString );
		m_skillBonus = TDBID.Create( ( "BaseStats." + skillString ) + "SkillcheckBonus" );
		m_requiredLevel = -1;
	}

	public override function GetDescription( requester : GameObject ) : Condition
	{
		var description : Condition;
		description.description = GetConditionDescription( requester.GetGame() );
		description.passed = Evaluate( requester );
		return description;
	}

	private function GetConditionDescription( gi : GameInstance ) : String
	{
		var text : String;
		var skill : String;
		skill = TweakDBInterface.GetStatRecord( m_skillToCheck ).EnumName();
		text = ( ( "Attribute: " + skill ) + " " ) + ( ( String )( GetRequiredLevel( gi ) ) );
		return text;
	}

}

class GameplayPerkCondition extends GameplayConditionBase
{
	[ customEditor = "TweakDBGroupInheritance;Perk" ]
	instanceeditable var m_perkToCheck : TweakDBID;
	instanceeditable var m_difficulty : EGameplayChallengeLevel;

	public override function Evaluate( requester : GameObject ) : Bool
	{
		if( GetPlayerPerk( requester ) >= GetRequiredLevel() )
		{
			return true;
		}
		else
		{
			return false;
		}
	}

	private function GetPlayerPerk( requester : GameObject ) : Int32
	{
		var playerDevSystem : PlayerDevelopmentSystem;
		var player : GameObject;
		player = GetPlayer( requester );
		playerDevSystem = ( ( PlayerDevelopmentSystem )( GameInstance.GetScriptableSystemsContainer( player.GetGame() ).Get( 'PlayerDevelopmentSystem' ) ) );
		return ( ( Int32 )( playerDevSystem.GetPerkLevel( player, GetPerkType() ) ) );
	}

	private function GetRequiredLevel() : Int32
	{
		return RPGManager.CheckDifficultyToPerkLevel( GetPerkType(), m_difficulty, m_entityID );
	}

	private function GetPerkType() : gamedataPerkType
	{
		return TweakDBInterface.GetPerkRecord( m_perkToCheck ).Type();
	}

	public override function GetDescription( requester : GameObject ) : Condition
	{
		var description : Condition;
		description.description = GetConditionDescription();
		description.passed = Evaluate( requester );
		return description;
	}

	private function GetConditionDescription() : String
	{
		var text : String;
		var perk : String;
		var max : String;
		var perkLevels : array< weak< PerkLevelData_Record > >;
		perk = TweakDBInterface.GetPerkRecord( m_perkToCheck ).Loc_name_key();
		TweakDBInterface.GetPerkRecord( m_perkToCheck ).Levels( perkLevels );
		max = ( ( String )( perkLevels.Size() ) );
		text = ( ( ( ( "Has perk: " + perk ) + " " ) + ( ( String )( GetRequiredLevel() ) ) ) + "/" ) + max;
		return text;
	}

}

class GameplayItemCondition extends GameplayConditionBase
{
	[ customEditor = "TweakDBGroupInheritance;Item" ]
	instanceeditable var m_itemToCheck : TweakDBID;

	public override function Evaluate( requester : GameObject ) : Bool
	{
		var transactionSystem : TransactionSystem;
		var itemID : ItemID;
		transactionSystem = GameInstance.GetTransactionSystem( requester.GetGame() );
		itemID = ItemID.FromTDBID( m_itemToCheck );
		return transactionSystem.HasItem( GetPlayer( requester ), itemID );
	}

	public override function GetDescription( requester : GameObject ) : Condition
	{
		var description : Condition;
		description.description = GetConditionDescription();
		description.passed = Evaluate( requester );
		return description;
	}

	private function GetConditionDescription() : String
	{
		var text : String;
		var item : String;
		item = ( ( String )( TweakDBInterface.GetItemRecord( m_itemToCheck ).DisplayName() ) );
		text = "Has item: " + item;
		return text;
	}

}

class GameplayCyberwareCondition extends GameplayConditionBase
{
	[ customEditor = "TweakDBGroupInheritance;Item" ]
	instanceeditable var m_cyberwareToCheck : TweakDBID;

	public override function Evaluate( requester : GameObject ) : Bool
	{
		var equipmentSystem : EquipmentSystem;
		var itemID : ItemID;
		equipmentSystem = ( ( EquipmentSystem )( GameInstance.GetScriptableSystemsContainer( GetPlayer( requester ).GetGame() ).Get( 'CyberwareSystem' ) ) );
		itemID = ItemID.CreateQuery( m_cyberwareToCheck );
		return equipmentSystem.GetPlayerData( GetPlayer( requester ) ).IsEquipped( itemID );
	}

	public override function GetDescription( requester : GameObject ) : Condition
	{
		var description : Condition;
		description.description = GetConditionDescription();
		description.passed = Evaluate( requester );
		return description;
	}

	private function GetConditionDescription() : String
	{
		var text : String;
		var item : String;
		item = ( ( String )( TweakDBInterface.GetItemRecord( m_cyberwareToCheck ).DisplayName() ) );
		text = ( "Has installed " + item ) + " cyberware";
		return text;
	}

}

class GameplayFactCondition extends GameplayConditionBase
{
	instanceeditable var m_factName : CName;
	instanceeditable var m_value : Int32;
	instanceeditable var m_comparisonType : ECompareOp;
	instanceeditable var m_description : String;
	default m_description = "Quest progress";

	public override function Evaluate( requester : GameObject ) : Bool
	{
		var factValue : Int32;
		factValue = GameInstance.GetQuestsSystem( requester.GetGame() ).GetFact( m_factName );
		return Compare( m_comparisonType, factValue, m_value );
	}

	public override function GetDescription( requester : GameObject ) : Condition
	{
		var description : Condition;
		description.description = m_description;
		description.passed = Evaluate( requester );
		return description;
	}

}

class GameplayStatCondition extends GameplayConditionBase
{
	private var m_statToCheck : TweakDBID;
	private instanceeditable var m_stat : EDeviceChallengeAttribute;
	private instanceeditable var m_difficulty : EGameplayChallengeLevel;

	public override function Evaluate( requester : GameObject ) : Bool
	{
		if( GetPlayerStat( requester ) >= GetRequiredLevel( requester.GetGame() ) )
		{
			return true;
		}
		else
		{
			return false;
		}
	}

	public function GetRequiredLevel( gi : GameInstance ) : Int32
	{
		return RPGManager.CheckDifficultyToStatValue( gi, GetStatType(), m_difficulty, m_entityID );
	}

	public function GetPlayerStat( requester : GameObject ) : Int32
	{
		var statsSystem : StatsSystem;
		statsSystem = GameInstance.GetStatsSystem( requester.GetGame() );
		return ( ( Int32 )( statsSystem.GetStatValue( GetPlayer( requester ).GetEntityID(), GetStatType() ) ) );
	}

	private function GetStatType() : gamedataStatType
	{
		m_statToCheck = TDBID.Create( "BaseStats." + ( ( String )( m_stat ) ) );
		return TweakDBInterface.GetStatRecord( m_statToCheck ).StatType();
	}

	public override function GetDescription( requester : GameObject ) : Condition
	{
		var description : Condition;
		description.description = GetConditionDescription( requester.GetGame() );
		description.passed = Evaluate( requester );
		return description;
	}

	private function GetConditionDescription( gi : GameInstance ) : String
	{
		var text : String;
		var stat : String;
		stat = TweakDBInterface.GetStatRecord( m_statToCheck ).EnumName();
		text = ( ( "Stat: " + stat ) + " " ) + ( ( String )( GetRequiredLevel( gi ) ) );
		return text;
	}

	public function SetProperties( sel_stat : EDeviceChallengeAttribute, sel_difficulty : EGameplayChallengeLevel )
	{
		m_stat = sel_stat;
		m_difficulty = sel_difficulty;
	}

}

