class_name StateModifier
extends Reference
## State modification
##
## A state modifier doesn't have any direct control of a game object. 
## They are transfered from the enter and exit of other states and 
## influence the movement or animation of their parent states. 
## Rather than going full into paralell state machines I hope that this 
## modifier will be suitable for a basic state machine.
##
## @WIP

# Used for mutually exclusive modifiers to aid merging 
enum TYPE {
	NONE, # Usually just a physics modifier
	EXIT_ANIMATION, # Adds an animation at the end? Not really sure anymore
	ANIMATION_SUFFIX, # Adds an animation suffix to aid slightly modified animations
	REPLACE_ANIMATION # Completely replaces a state animation.
}

enum EVENT_ID {
	ACTIVATED, 
	DEACTIVATED
}

var debug: bool = false

##TODO: Animation speed

## Modification Type
## if an animation is specified, the default behavior will be just to override
## the state animation. Or perform a 'Replace Animation'
var modifier_type = TYPE.NONE

var name :String = ''
#var ready :bool = false
var is_active: bool = false

signal modifier_event(event_id )

# Move Speed in Pixels Per Second
# These should only apply if Modification Type Set to None.
# (But I'm not sure if I like that model.)
#var move_speed: float
#var move_speed_modifier: float = 0
#var move_speed_modifier_decay: float = 0

#var gravity: int = ProjectSettings.get_setting("physics/2d/default_gravity")


# Attempting to use this as an animation suffix that can linger after
# state transition like 'run-fire' to 'idle-fire' 'jump-fire' etc.
#var animation_suffix: bool = false
#var pre_append_animation: bool = false

# not sure if I can do the array thing from state change. Maybe? 
# disabling this sequencing for now. 
# export(Array, String) var animation_sequence
# var animation_index: int = 0
# var current_animation_sequence: int = 0


#var animation_sequence_timer: Timer

var timeout: Timer
var timeout_seconds: float = 0.0

# Meant to be called on timeout or other counters this modifier may have.
# Should be updated whenever modifier owner transfers
var state_call_function: FuncRef

#func merge_modifier(merging_mod: ModifierProperties):
#	if merging_mod.modifier_type != TYPE.NONE:
#		print("Warning Merging modifier types that aren't set to 'none' is not supported!")
#		return

#func get_modifier_properties() -> ModifierProperties:
#	#( p_move_speed:float, p_gravity:int , p_move_acceleration , p_move_speed_modifier:float,
#	#	 p_move_modifier_move_acceleration:float, p_jerk_factor: float):
#	var mp = ModifierProperties.new( modifier_properties.move_speed,
#									modifier_properties.gravity, 
#									modifier_properties.move_acceleration,
#									modifier_properties.move_speed_modifier,
#									modifier_properties.move_modifier_move_acceleration,
#									modifier_properties.jerk_factor)
#	mp.directional_modifier = modifier_properties.directional_modifier
#	return mp

func setup(modifier_name:String, type = TYPE.NONE,_timeout_seconds : float = 0):
	name = modifier_name 
	modifier_type = type

	if _timeout_seconds > 0:
		timeout = Timer.new()
		timeout.wait_time = _timeout_seconds
		timeout.one_shot = true
		timeout.autostart = false
		timeout.connect("timeout",self,"deactivate")

func reset():
	name = ''
	modifier_type = TYPE.NONE

func copy(_copy_state: StateModifier):
	_copy_state.name = name
	_copy_state.modifier_type = modifier_type


func merge(_merge_from_modifier: StateModifier):
	pass

func activate():
	is_active = true
	if timeout != null:
		timeout.start()
	emit_signal("modifier_event",EVENT_ID.ACTIVATED)

func deactivate():
	is_active = false
	print(name," <- Got call to deactivate.")
	emit_signal("modifier_event",EVENT_ID.DEACTIVATED)

#func ready(modifier_name:String, anim_name:String = '', type = TYPE.NONE, timeout : float = 0, parent:Node = null, function_name : String = "") -> Timer:
#	name = modifier_name 
#	# If somebody forgot to specify the type
#	if anim_name != '' and type == TYPE.NONE:
#		modifier_type = TYPE.REPLACE_ANIMATION
#	animation_name = anim_name
#	modifier_type = type
##	if parent != null and function_name != "":
##		state_call_function = funcref(parent, function_name)
#
##	modifier_properties = ModifierProperties.new(0,0,0,0,0,0)
#
#	if timeout > 0:
#		state_timeout = Timer.new()
#		state_timeout.wait_time = timeout
#		state_timeout.one_shot = true
#		state_timeout.autostart = false
#		return state_timeout
#	#add_child(state_timeout)
#	#ModifierProperties.new()
#	return null


## Transfer and callback related methods. These sort of worked but I didn't end up using them
## They're an interesting idea though.
#func transfer_owner(parent:Node):
#	print("Modifier owner will now be: ", parent.name)
#	state_call_function = funcref(parent, 'update_animation')

func _on_Timer_timeout():
	#print("Oh Crap! I can't beleive it worked")
	if state_call_function:
		if state_call_function.is_valid():
			state_call_function.call_func()
		else:
			print("Warning! Modifier timed out with no callback to alert.")
	else:
		print("Warning! no function applies.")
