extends Node

class Someone extends Object:
	var name : String
	
	func _init(name : String) -> void:
		self.name = name	

class Motion extends Object:
	var originator : Someone
	var animation : String
	var stamina_change : float
	
	func _init(originator : Someone, animation : String, stamina_change : float = 0) -> void:
		self.originator = originator
		self.animation = animation
		self.stamina_change = stamina_change

class Recover extends Motion:
	''' Animation '''
	pass

class Reaction extends Motion:
	var hp_change : float

	func _init(originator : Someone, animation: String, stamina_costs: float, hp_change : float):
		super._init(originator, animation, -stamina_costs)
		self.hp_change = hp_change

class Counter extends Reaction:
	var damage : float

	func _init(originator : Someone, animation: String, stamina_costs: float, damage : float):
		super._init(originator, animation, -stamina_costs, 0)
		self.damage = damage

class Defense extends Reaction:
	var successful : bool

	func _init(originator : Someone, animation: String, stamina_costs: float, hp_change : float):
		super._init(originator, animation, -stamina_costs, hp_change)
		self.successful = hp_change == 0.0

class Block extends Defense:
	func _init(originator : Someone, animation : String, stamina_costs: float, hp_change : float):
		super._init(originator, animation, stamina_costs, hp_change)

class Evade extends Defense:
	''' Successfully, evaded? '''
	
	func _init(originator : Someone, animation : String, stamina_costs: float, hp_change : float):
		super._init(originator, animation, stamina_costs, hp_change)

class Absorb extends Reaction:
	''' Actually, accept being hit '''
		
	func _init(originator : Someone, animation: String, stamina_costs: float, hp_change : float):
		super._init(originator, animation, -stamina_costs, hp_change)


class Action extends Motion:
	pass

class ActionOnSelf extends Action:
	pass

class Wait extends ActionOnSelf:
	func _init(originator : Someone, animation : String, stamina_gain : float):
		super._init(originator, animation, stamina_gain)

class Buff extends ActionOnSelf:
	func _init(originator : Someone, animation : String) -> void:
		super._init(originator, animation, 1.0)

class ActionOnOpponent extends Action:
	var opponent : Someone
	var reaction : Reaction

	func _init(originator : Someone, animation : String, opponent : Someone, stamina_costs : float, reaction : Reaction) -> void:
		super._init(originator, animation, -stamina_costs)
		self.opponent = opponent
		self.reaction = reaction

class Attack extends ActionOnOpponent:
	var damage : float
	
	func _init(originator : Someone, animation : String, opponent : Someone, stamina_costs : float, reaction : Reaction) -> void:
		super._init(originator, animation, opponent, stamina_costs, reaction)

class Debuff extends ActionOnOpponent:
	func _init(originator : Someone, animation : String, opponent : Someone, stamina_costs : float, reaction : Reaction) -> void:
		super._init(originator, animation, opponent, stamina_costs, reaction)

class PlayerAnimation extends Object:
	var animation : String
	var hp_change : float 
	var stamina_change : float

class Round extends Object:
	var action: int
	var animations : Array[PlayerAnimation]

func convertReaction2PlayerAnimation(reaction : Reaction) -> PlayerAnimation:
	if reaction == null:
		return null
	var a = PlayerAnimation.new()
	a.animation = reaction.animation
	a.hp_change = -reaction.hp_change
	return a

func getReaction(motion : Motion) -> Reaction:
	if motion is ActionOnOpponent:
		return motion.reaction
	
	return null

func convertMotion2PlayerAnimation(motion : Motion) -> PlayerAnimation:
	var a = PlayerAnimation.new()
	a.animation = motion.animation
	a.stamina_change = motion.stamina_change
	return a

func convertMotion2Round(lhs : Someone, rhs : Someone, motion : Motion) -> Round:
	var round = Round.new()

	round.action = 0 if motion.originator == lhs else 1
	round.animations.append(convertMotion2PlayerAnimation(motion))
	var reaction = getReaction(motion)
	round.animations.append(convertReaction2PlayerAnimation(reaction))

	if reaction is Counter:
		round.animations[0].hp_change = -reaction.damage
	
	return round

# TODO: breakdown to a simpler transferable class
func convert(lhs : Someone, rhs : Someone, motions : Array[Motion]) -> Array[Round]:
	var rounds : Array[Round] = []
	for motion in motions:
		rounds.push_back(convertMotion2Round(lhs, rhs, motion))
		
	return rounds

func _init() -> void:
	var player1 : Someone = Someone.new("John")
	var player2 : Someone = Someone.new("Joe")

	var rounds : Array[Motion] = [
		Attack.new(player1, "Kick", player2, 1.0, Absorb.new(player2, "Hit", 1, 12.0)),
		Buff.new(player2, "SSJ"),
		Attack.new(player1, "Punch", player2, 2.0, Block.new(player2, "Block", 1.0, true)),
		Wait.new(player2, "Wait", 5.0)
	]

	var r2 = self.convert(player1, player2, rounds)
	
	for r in r2:
		var activeIndex = r.action
		var reactiveIndex = 0 if r.action == 1 else 0
		var orientation = "Left" if r.action == 1 else "Right"
		
		print("%s Player {'Animation': '%s', 'hp_change': %f, 'stamina_change': %f}" % [orientation, r.animations[0].animation, r.animations[0].hp_change, r.animations[0].stamina_change])
		if r.animations[1] != null:	
			print("Other Player {'Animation': '%s', 'hp_change': %f, 'stamina_change': %f}" % [r.animations[1].animation, r.animations[1].hp_change, r.animations[1].stamina_change])
		print()
