extends "res://objects/characters/character.gd"

const SPEED = 400
const JUMP_HEIGHT = 1000
const STRIKED_HEIGHT = 400
export var background_scene : Resource

onready var level = get_parent()
onready var main = level.get_parent()

const ANIMATIONS = {
	"idle": {
		"animation": "idle",
		"transistion": "idle",
		"blocks": []
	},
	"run": {
		"animation": "run",
		"transistion": "run",
		"blocks": []
	},
	"jump_start": {
		"animation": "jump_start",
		"transistion": "jump",
		"blocks": ["idle", "run", "fall_start", "fall", "fall_end"]
	},
	"jump": {
		"animation": "jump",
		"transistion": "jump",
		"blocks": ["idle", "run", "fall_start", "fall", "fall_end"]
	},
	"jump_end": {
		"animation": "jump_end",
		"transistion": "idle",
		"blocks": ["idle", "run", "fall_start", "fall", "fall_end"]
	},
	"fall_start": {
		"animation": "fall_start",
		"transistion": "fall",
		"blocks": ["idle", "run", "fall", "fall_end", "jump_start", "jump", "jump_end"]
	},
	"fall": {
		"animation": "fall",
		"transistion": "fall",
		"blocks": ["idle", "run", "fall_start", "jump_start", "jump", "jump_end"]
	},
	"fall_end": {
		"animation": "fall_end",
		"transistion": "idle",
		"blocks": ["idle", "run", "fall_start", "fall", "jump_start", "jump", "jump_end"]
	},
	"striked_start": {
		"animation": "jump_start",
		"transistion": "striked",
		"blocks": ["idle", "run", "fall_start", "fall", "fall_end", "jump_start", "jump", "jump_end"]
	},
	"striked": {
		"animation": "jump",
		"transistion": "striked_end",
		"blocks": ["idle", "run", "fall_start", "fall", "fall_end", "jump_start", "jump", "jump_end"]
	},
	"striked_end": {
		"animation": "hurt",
		"transistion": "idle",
		"blocks": ["idle", "run", "fall_start", "fall", "fall_end", "jump_start", "jump", "jump_end"]
	}
}
var player_state = "idle"
var invincible_hit = false

var score = 0

func _ready():
	$Camera2D.add_child(background_scene.instance())
	$Sprite.connect("animation_finished", self, "_next_player_state")
	$Sprite.animation = ANIMATIONS[player_state]['animation']
	
func _physics_process(delta):
	if motion.y > 5 * GRAVITY and not $RayBottomLeft.is_colliding() and not $RayBottomRight.is_colliding():
		_set_player_state("fall_start")
	
	if Input.is_action_pressed("move_left") and not Input.is_action_pressed("move_right") \
	and not player_state in ["striked_start", "striked", "striked_end"]:
		move_left(SPEED)
	elif Input.is_action_pressed("move_right") and not Input.is_action_pressed("move_left") \
	and not player_state in ["striked_start", "striked", "striked_end"]:
		move_right(SPEED)
	elif player_state in ["idle", "run", "jump", "jump_end", "fall_end", "striked_end"]:
		move_stop()
	
	if is_on_floor():
		_end_animation()
		
	if Input.is_action_just_pressed("jump"):
		if $RayBottomLeft.is_colliding() or $RayBottomRight.is_colliding():
			jump()
	
func _next_player_state():
	player_state = ANIMATIONS[player_state]["transistion"]
	$Sprite.animation = ANIMATIONS[player_state]['animation']
	
func _set_player_state(new_state):
	if not new_state in ANIMATIONS[player_state]["blocks"]:
		player_state = new_state
		$Sprite.animation = ANIMATIONS[player_state]['animation']
		return true
	return false

func move_right(delta):
	_set_player_state("run")
	get_node("Sprite").set_flip_h(false)
	motion.x = delta

func move_left(delta):
	_set_player_state("run")
	get_node("Sprite").set_flip_h(true)
	motion.x = -delta

func move_stop():
	_set_player_state("idle")
	motion.x = 0

func jump():
	if _set_player_state("jump_start"):
		if get_floor_velocity().y < 0:
			position.y += get_floor_velocity().y * get_physics_process_delta_time() \
			- GRAVITY * get_physics_process_delta_time() - 3
		motion.y -= JUMP_HEIGHT

func _on_GroundCheck_body_entered(body):
	_end_animation()

func _end_animation():
	if motion.y > 0 and player_state in ["jump_start", "jump"]:
		_set_player_state("jump_end")
	if motion.y > 0 and player_state in ["fall_start", "fall"]:
		_set_player_state("fall_end")
	if motion.y > 0 and player_state in ["striked_start", "striked"]:
		_set_player_state("striked_end")

func monster_hit(direction : int, damage: int):
	if not invincible_hit:
		invincible_hit = true
		_set_player_state("striked_start")
		motion.y = -STRIKED_HEIGHT
		motion.x = direction * 5
		yield(get_tree().create_timer(1.0), "timeout")
		invincible_hit = false

func _on_Enemy_Entered(body):
	body.stomped_on_head()
	_set_player_state("jump")

func coin_collected(value):
	main.add_score(value)

func _on_screen_exited():
	if motion.y > 1:
		health = 0
		main.player_died()
