class NewPerksPerkItemLogicController extends inkLogicController
{
	private editable var m_icon : inkImageRef;
	private editable var m_iconGhost : inkImageRef;
	private editable var m_lockIcon : inkWidgetRef;
	private editable var m_requiredPointsText : inkTextRef;
	private editable var m_levelText : inkTextRef;
	private editable var m_DEV_notYetImplemented : inkWidgetRef;
	private var m_container : weak< NewPerksPerkContainerLogicController >;
	private var m_initData : NewPerksPerkItemInitData;
	private var m_isUnlocked : Bool;
	private var m_currentLevel : Int32;
	private var m_hovered : Bool;
	private var m_maxedAnimProxy : inkAnimProxy;
	private var m_animProxies : array< inkAnimProxy >;
	private var m_isRelic : Bool;

	protected event OnInitialize()
	{
		RegisterToCallback( 'OnRelease', this, 'OnRelease' );
		RegisterToCallback( 'OnHoverOver', this, 'OnHoverOver' );
		RegisterToCallback( 'OnHoverOut', this, 'OnHoverOut' );
		m_animProxies.Resize( ( ( Int32 )( NewPerkCellAnimationType.COUNT ) ) );
	}

	public function Initialize( container : weak< NewPerksPerkContainerLogicController >, initData : NewPerksPerkItemInitData )
	{
		m_container = container;
		m_initData = initData;
		inkWidgetRef.SetVisible( m_DEV_notYetImplemented, m_initData.maxPerkLevel == 0 );
		inkTextRef.SetText( m_requiredPointsText, IntToString( m_initData.requiredAttributePoints ) );
		inkTextRef.SetVisible( m_requiredPointsText, !( m_initData.isAttributeRequirementMet ) );
		if( TDBID.IsValid( m_initData.icon ) )
		{
			InkImageUtils.RequestSetImage( this, m_icon, m_initData.icon );
			InkImageUtils.RequestSetImage( this, m_iconGhost, m_initData.icon );
		}
		m_isRelic = m_initData.perkRecord.Attribute().Type() == gamedataAttributeDataType.EspionageAttributeData;
		UpdateState();
	}

	public function GetContainer() : weak< NewPerksPerkContainerLogicController >
	{
		return m_container;
	}

	public function GetSlotIdentifier() : gamedataNewPerkSlotType
	{
		return m_container.GetSlotIdentifier();
	}

	public function GetPerkRecord() : weak< NewPerk_Record >
	{
		return m_initData.perkRecord;
	}

	public function GetPerkType() : gamedataNewPerkType
	{
		return m_initData.perkType;
	}

	public function GetMaxLevel() : Int32
	{
		return m_initData.maxPerkLevel;
	}

	public function IsUnlocked() : Bool
	{
		return m_isUnlocked;
	}

	public function IsMaxed() : Bool
	{
		return m_currentLevel == m_initData.maxPerkLevel;
	}

	public function IsAttributeRequirementMet() : Bool
	{
		return m_initData.isAttributeRequirementMet;
	}

	public function SetLevel( level : Int32 )
	{
		inkTextRef.SetText( m_levelText, ( IntToString( level ) + "/" ) + IntToString( m_initData.maxPerkLevel ) );
		m_currentLevel = level;
		UpdateState();
	}

	public function GetLevel() : Int32
	{
		return m_currentLevel;
	}

	public function SetUnlocked( value : Bool )
	{
		m_isUnlocked = value;
		inkWidgetRef.SetVisible( m_lockIcon, !( value ) );
		UpdateState();
	}

	public function SetAttributeRequirementMet( value : Bool )
	{
		m_initData.isAttributeRequirementMet = value;
		UpdateState();
	}

	public function UpdateState()
	{
		if( !( m_initData.isAttributeRequirementMet ) )
		{
			if( m_hovered )
			{
				GetRootWidget().SetState( 'RequirementNotMetHover' );
			}
			else
			{
				GetRootWidget().SetState( 'RequirementNotMet' );
			}
		}
		else if( !( m_isUnlocked ) )
		{
			if( m_hovered )
			{
				GetRootWidget().SetState( 'LockedHover' );
			}
			else
			{
				GetRootWidget().SetState( 'Locked' );
			}
		}
		else
		{
			if( m_currentLevel > 0 )
			{
				if( m_initData.stat == gamedataStatType.Espionage || m_initData.category == gamedataNewPerkCategoryType.SimpleNewPerkCategory )
				{
					if( m_hovered )
					{
						GetRootWidget().SetState( 'BoughtHover' );
					}
					else
					{
						GetRootWidget().SetState( 'Bought' );
					}
				}
				else if( m_currentLevel < m_initData.maxPerkLevel )
				{
					if( m_hovered )
					{
						GetRootWidget().SetState( 'PartiallyInvestedHover' );
					}
					else
					{
						GetRootWidget().SetState( 'PartiallyInvested' );
					}
				}
				else
				{
					if( m_hovered )
					{
						GetRootWidget().SetState( 'FullyInvestedHover' );
					}
					else
					{
						GetRootWidget().SetState( 'FullyInvested' );
					}
				}
			}
			else
			{
				if( m_hovered )
				{
					GetRootWidget().SetState( 'Hover' );
				}
				else
				{
					GetRootWidget().SetState( 'Default' );
				}
			}
		}
	}

	protected event OnRelease( evt : inkPointerEvent )
	{
		var action : CName;
		var perkEvt : NewPerkClickEvent;
		if( evt.IsAction( 'buy_perk' ) )
		{
			action = 'buy_perk';
		}
		else if( evt.IsAction( 'sell_perk' ) )
		{
			action = 'sell_perk';
		}
		else
		{
			return true;
		}
		perkEvt = new NewPerkClickEvent;
		perkEvt.controller = this;
		perkEvt.action = action;
		QueueEvent( perkEvt );
	}

	private function GetAnimationPrefix() : String
	{
		if( m_initData.stat == gamedataStatType.Espionage )
		{
			if( m_initData.category == gamedataNewPerkCategoryType.SimpleNewPerkCategory )
			{
				return "spy_cell_";
			}
			else
			{
				return "spy_cell_master_";
			}
		}
		else
		{
			if( m_initData.category == gamedataNewPerkCategoryType.SimpleNewPerkCategory )
			{
				return "perk_cell_";
			}
			else if( m_initData.category == gamedataNewPerkCategoryType.MilestoneNewPerkCategory )
			{
				return "milestone_cell_";
			}
			else
			{
				return "master_cell_";
			}
		}
		return "";
	}

	private function GetAnimationSuffix( type : NewPerkCellAnimationType ) : String
	{
		switch( type )
		{
			case NewPerkCellAnimationType.Bought:
				return "buy";
			case NewPerkCellAnimationType.Maxed:
				return "maxed";
			case NewPerkCellAnimationType.Locked:
				return "locked";
			case NewPerkCellAnimationType.HoverOver:
				return "hoverover";
			case NewPerkCellAnimationType.HoverOut:
				return "hoverout";
			case NewPerkCellAnimationType.Sold:
				return "sell";
			case NewPerkCellAnimationType.Reminder:
				return "remind";
			case NewPerkCellAnimationType.SellLocked:
				return "sell_locked";
			case NewPerkCellAnimationType.InsufficientPoints:
				return "insufficient_points";
			case NewPerkCellAnimationType.MaxedLocked:
				return "maxed_locked";
		}
		return "";
	}

	private function GetAnimationSound( type : NewPerkCellAnimationType ) : CName
	{
		switch( type )
		{
			case NewPerkCellAnimationType.Bought:
				if( m_isRelic )
				{
					return 'ui_menu_perk_buy_relic';
				}
				else if( m_initData.category == gamedataNewPerkCategoryType.SimpleNewPerkCategory )
				{
					return 'ui_menu_perk_buy_minor';
				}
				else if( m_initData.category == gamedataNewPerkCategoryType.MasterNewPerkCategory )
				{
					return 'ui_menu_perk_buy_master';
				}
				else
				{
					return 'ui_menu_perk_buy_major_tier';
				}
			case NewPerkCellAnimationType.Maxed:
				if( m_isRelic )
				{
					return 'ui_menu_perk_buy_relic';
				}
				else if( m_initData.category == gamedataNewPerkCategoryType.SimpleNewPerkCategory )
				{
					return 'ui_menu_perk_buy_minor';
				}
				else if( m_initData.category == gamedataNewPerkCategoryType.MasterNewPerkCategory )
				{
					return 'ui_menu_perk_buy_master';
				}
				else
				{
					return 'ui_menu_perk_buy_major_max';
				}
			case NewPerkCellAnimationType.Locked:
				return 'ui_menu_perk_buy_fail';
			case NewPerkCellAnimationType.HoverOver:
				return '';
			case NewPerkCellAnimationType.HoverOut:
				return '';
			case NewPerkCellAnimationType.Sold:
				return 'ui_menu_perk_buy';
			case NewPerkCellAnimationType.Reminder:
				return '';
			case NewPerkCellAnimationType.SellLocked:
				return 'ui_menu_perk_buy_fail';
		}
		return '';
	}

	private function GetRumbleStrength( type : NewPerkCellAnimationType ) : RumbleStrength
	{
		switch( type )
		{
			case NewPerkCellAnimationType.Bought:
				if( m_isRelic )
				{
					return RumbleStrength.Heavy;
				}
				else if( m_initData.category == gamedataNewPerkCategoryType.SimpleNewPerkCategory )
				{
					return RumbleStrength.Light;
				}
				else if( m_initData.category == gamedataNewPerkCategoryType.MasterNewPerkCategory )
				{
					return RumbleStrength.Heavy;
				}
				else
				{
					return RumbleStrength.Heavy;
				}
			case NewPerkCellAnimationType.Maxed:
				return RumbleStrength.Heavy;
			case NewPerkCellAnimationType.Sold:
				return RumbleStrength.SuperLight;
		}
		return RumbleStrength.SuperLight;
	}

	private function GetTargetAnimation( type : NewPerkCellAnimationType ) : CName
	{
		var animationName : String;
		animationName += GetAnimationPrefix();
		animationName += GetAnimationSuffix( type );
		return StringToName( animationName );
	}

	public function PlayAnimation( type : NewPerkCellAnimationType )
	{
		var i : Int32;
		i = ( ( Int32 )( type ) );
		if( m_animProxies[ i ].IsPlaying() )
		{
			m_animProxies[ i ].GotoEndAndStop();
		}
		m_animProxies[ i ] = PlayLibraryAnimation( GetTargetAnimation( type ) );
		PlaySoundForAnim( type );
	}

	public function StopAllAnimations()
	{
		var i : Int32;
		for( i = 0; i < m_animProxies.Size(); i += 1 )
		{
			if( m_animProxies[ i ].IsPlaying() )
			{
				m_animProxies[ i ].GotoEndAndStop();
			}
		}
	}

	private function PlaySoundForAnim( type : NewPerkCellAnimationType )
	{
		var soundName : CName;
		var rumbleStrength : RumbleStrength;
		var evt : PlayNewPerksSoundEvent;
		soundName = GetAnimationSound( type );
		rumbleStrength = GetRumbleStrength( type );
		if( soundName == '' )
		{
			return;
		}
		evt = new PlayNewPerksSoundEvent;
		evt.soundName = soundName;
		evt.rumbleStrength = rumbleStrength;
		QueueEvent( evt );
	}

	protected event OnHoverOver( evt : inkPointerEvent )
	{
		var e : NewPerkHoverOverEvent;
		e = new NewPerkHoverOverEvent;
		e.controller = this;
		e.evt = evt;
		e.perkData = GetNewPerkDisplayData();
		QueueEvent( e );
		m_hovered = true;
		UpdateState();
		PlayAnimation( NewPerkCellAnimationType.HoverOver );
	}

	protected event OnHoverOut( evt : inkPointerEvent )
	{
		var e : NewPerkHoverOutEvent;
		e = new NewPerkHoverOutEvent;
		e.controller = this;
		e.evt = evt;
		QueueEvent( e );
		m_hovered = false;
		UpdateState();
		PlayAnimation( NewPerkCellAnimationType.HoverOut );
	}

	public function GetNewPerkDisplayData() : NewPerkDisplayData
	{
		var perkData : NewPerkDisplayData;
		perkData = new NewPerkDisplayData;
		perkData.m_type = m_initData.perkType;
		perkData.m_area = m_container.GetSlotIdentifier();
		perkData.m_binkRef = m_initData.binkRef;
		perkData.m_level = m_currentLevel;
		perkData.m_maxLevel = m_initData.maxPerkLevel;
		perkData.m_locked = !( m_isUnlocked );
		return perkData;
	}

}

class NewPerkClickEvent extends Event
{
	var controller : weak< NewPerksPerkItemLogicController >;
	var action : CName;
}

class NewPerkHoverOverEvent extends Event
{
	var controller : weak< NewPerksPerkItemLogicController >;
	var evt : inkPointerEvent;
	var perkData : NewPerkDisplayData;
}

class NewPerkHoverOutEvent extends Event
{
	var controller : weak< NewPerksPerkItemLogicController >;
	var evt : inkPointerEvent;
}

class NewPerksPerkItemInitData
{
	var perkRecord : weak< NewPerk_Record >;
	var perkType : gamedataNewPerkType;
	var requiredAttributePoints : Int32;
	var isAttributeRequirementMet : Bool;
	var maxPerkLevel : Int32;
	var icon : TweakDBID;
	var binkRef : ResRef;
	var category : gamedataNewPerkCategoryType;
	var stat : gamedataStatType;
}

enum NewPerkCellAnimationType
{
	Bought = 0,
	Maxed = 1,
	Locked = 2,
	HoverOver = 3,
	HoverOut = 4,
	Sold = 5,
	Reminder = 6,
	SellLocked = 7,
	InsufficientPoints = 8,
	MaxedLocked = 9,
	COUNT = 10,
	INVALID = -1,
}

