extends Node2D

const ANIM_RATE_DEFAULT = 3.5
const ANIM_RATE_AGGRESSIVE = 6.0
const ANIM_RATE_CONTENT = 1.0

const EXCITEMENT_MIN_SPEED = 150
const EXCITEMENT_MAX_SPEED = 350

# Mood = r: <aggression>, g: <neediness>, b: <contentment>
# <aggression> Affects how strong a players push is and how strong the player's collision with the world will be.
# <neediness> Affects how quickly and strongly the player will follow the mouse
# <contentment> Affects how slowly mood color is shifted back to neutral and widens comfort distance
var _mood = Color.black

onready var _spr = get_parent().get_node("Sprite")
onready var _body_radius = get_parent().get_node("CollisionShape2D").shape.radius

func adjust_mood(r, g, b):
	_mood.r = clamp(_mood.r + r, 0.0, 1.0)
	_mood.g = clamp(_mood.g + g, 0.0, 1.0)
	_mood.b = clamp(_mood.b + b, 0.0, 1.0)
	_spr.material.set_shader_param("cell_color", _mood);
	
	if is_aggressive():
		_spr.material.set_shader_param("cell_energy", ANIM_RATE_AGGRESSIVE)
	elif is_content():
		_spr.material.set_shader_param("cell_energy", ANIM_RATE_CONTENT)
	else:
		_spr.material.set_shader_param("cell_energy", ANIM_RATE_DEFAULT)

func adjust_mood_from_color(c):
	if c.r != c.g or c.r != c.b: # Only adjust mood if not all values are the same.
		# Even if not all the same, there must be a single dominant color for mood to be adjusted.
		if c.r > c.g and c.r > c.b:
			adjust_mood(0.25, 0.0, 0.0)
		if c.g > c.r and c.g > c.b:
			adjust_mood(0.0, 0.25, 0.0)
		if c.b > c.r and c.b > c.g:
			adjust_mood(0.0, 0.0, 0.25)

func is_aggressive():
	return _mood.r > _mood.g and _mood.r > _mood.b

func is_needie():
	return _mood.g > _mood.r and _mood.g > _mood.b

func is_content():
	return _mood.b > _mood.r and _mood.b > _mood.g

func is_neutral():
	return not is_aggressive() and not is_needie() and not is_content()

func get_aggression():
	return _mood.r

func get_need():
	return _mood.g

func get_contentment():
	return _mood.b

func get_comfort_distance():
	return get_parent().get_node("CollisionShape2D").shape.radius * 2.1

func get_mood_color():
	return _mood

func _agg_shift(in_air, speed):
	var v = -0.1 # By default, aggression is always lowering
	
	if in_air and speed >= EXCITEMENT_MIN_SPEED and speed <= EXCITEMENT_MAX_SPEED:
			v = 0.1 # If in the air, going at an "exciting" speed, aggression rises!
	elif is_aggressive():
		v = -0.05 # Otherwise, if we're dominantly aggressive, slow aggression cooldown.
		if speed > 1.0 and _mood.r * 0.5 > _mood.b and _mood.r * 0.5 > _mood.g:
			v = 0.0 # But, if we're moving and our aggression is more than twice the other emotions, don't cooldown at all.
	return v

func _need_shift(in_air, distance):
	var v = -0.1
	if in_air:
		# Decrease neediness faster while in air, as "player" is giving attension (in the air) or
		# otherwise excited!!
		v = -0.25
	else:
		var cdist = get_comfort_distance()
		if distance > cdist:
			v = 0.1
			if distance > cdist * 8.0:
				v = 0.25
	return v

func _con_shift(in_air, speed, distance):
	var v = -0.1
	if in_air and speed < EXCITEMENT_MIN_SPEED:
		v = 0.1
		if is_aggressive(): # Assuming aggression hasn't taken over...
			v = 0.05 # Levitating in the air is nice!
	else:
		var cdist = get_comfort_distance()
		if distance <= cdist:
			v = 0.1 # It's nice when the player is nearby
			if is_needie():
				v = 0.05 # My neediness is slowing my contentment.
		elif is_aggressive():
			v = -0.25 # If aggressive, reduce contentment a lot.
	return v

func shift_mood(delta, in_air, speed, distance):
	adjust_mood(
		_agg_shift(in_air, speed) * delta,
		_need_shift(in_air, distance) * delta,
		_con_shift(in_air, speed, distance) * delta
	)
