extends KinematicBody2D

const FLOOR_NORMAL = Vector2(0, -1)
const SLOPE_SLIDE_STOP = 1.0
const GRAVITY = 980.0
const WATER_DENSITY = 0.0

export(String, "jump1", "jump2") var jump_sound

export var can_double_jump = true
export var can_wall_jump = true
export var move_speed = 80.0
export var in_water_move_speed = 40.0
export var jump_force = 260.0
export var water_out_jump_force = 180.0
export var wall_jump_force = 200.0
export var acceleration = 1.4
export var in_water_acceleration = 2.0

var velocity = Vector2()
var floor_velocity = Vector2()
var anim = ""
var siding_left = false
var jumping = false
var double_jumping = false
var wall_jumping = false
var edge = false
var on_floor = false
var falling = false
var scream = false
var enable_scream = false
var is_dead =  false
var in_water = false
var has_key = false
var move_up = false

onready var explosion_scene = load("res://scenes/explosion.scn")
onready var left_wall = get_node("left_wall_check")
onready var right_wall = get_node("right_wall_check")
onready var ceil_check = get_node("ceil_check")
onready var edge_check = get_node("edge_check")


func _fixed_process(delta):
	
	var new_anim = "idle"
	var new_siding_left = siding_left

	var move_left = Input.is_action_pressed("ui_left")
	var move_right = Input.is_action_pressed("ui_right")
	var move_down = Input.is_action_pressed("ui_down")
	var jump = Input.is_action_just_pressed("ui_up")
	
	if in_water:

		var move_up = Input.is_action_pressed("ui_up")
		
		new_anim = "swim"
		
		velocity.y += WATER_DENSITY * delta
		
		if move_left:
			velocity.x -= in_water_acceleration
			new_siding_left = true
		elif move_right:
			velocity.x += in_water_acceleration
			new_siding_left = false
		if move_up:
			velocity.y -= in_water_acceleration
		elif move_down:
			velocity.y += in_water_acceleration
			
		var motion = velocity * delta
		if motion != Vector2(0,0):
			motion = move( motion )
			
		if right_wall.is_colliding() or left_wall.is_colliding():
			velocity.x = 0
			
		if edge_check.is_colliding() or ceil_check.is_colliding():
			velocity.y = 0
		
		if is_colliding():
			var normal = get_collision_normal()
			motion = normal.slide( motion ) 
			if motion != Vector2(0,0):
				move(motion)
		
		velocity.x = clamp(velocity.x, -in_water_move_speed, in_water_move_speed) 
		
		if (new_anim != anim):
			anim = new_anim
			get_node("anim").play(anim)
				
		get_node("anim").set_speed(lerp(1, 2, abs(velocity.x/100))) 
	
		if (new_siding_left != siding_left):
			if (new_siding_left):
				get_node("sprite").set_scale(Vector2(-1, 1))
			else:
				get_node("sprite").set_scale(Vector2(1, 1))
			siding_left = new_siding_left

		return
	
	velocity.y += GRAVITY * delta
	
	var target_speed = 0
	
	if move_left and !left_wall.is_colliding():
		if velocity.x > 0 and on_floor:
			velocity.x = 0
		velocity.x -= acceleration
		new_siding_left = true
	elif move_right and !right_wall.is_colliding():
		if velocity.x < 0 and on_floor:
			velocity.x = 0
		velocity.x += acceleration
		target_speed +=  1
		new_siding_left = false
	else:
		if on_floor:
			velocity.x = 0
			
	var motion = velocity * delta
	if motion != Vector2(0,0):
		motion = move( motion )
			
	if is_colliding():
		var normal = get_collision_normal()
		if normal.y < 0:
			if normal.y != -1:
				motion.y = 0
			else:
				if !on_floor:
					on_floor = true
					get_node("landing").set_emitting(true)
					audio.play_sound("landing")
				double_jumping = false
				jumping = false
				falling = false
			floor_velocity = get_collider_velocity()
			edge = !edge_check.is_colliding()
		motion = normal.slide( motion ) 
		if motion != Vector2(0,0):
			move(motion)
		velocity = normal.slide( velocity )
	else:
		on_floor = false
		if !jumping and !falling: 
			falling = true
			if abs(velocity.x) < 30:
				velocity.x = 0
				
	velocity.x = clamp(velocity.x, -move_speed, move_speed) 
	
	if (floor_velocity!=Vector2()):
		move(floor_velocity * delta)
		
	if jump: 
		if on_floor:
			velocity.y = -jump_force
			velocity.x *= 2
			on_floor = false
			audio.play_sound("jump")
		elif left_wall.is_colliding() and can_wall_jump and !move_left:
			velocity.y = -jump_force
			velocity.x = wall_jump_force
			new_siding_left = false
			audio.play_sound("jump")
		elif right_wall.is_colliding() and can_wall_jump and !move_right:
			velocity.y = -jump_force
			velocity.x = -wall_jump_force
			new_siding_left = true
			audio.play_sound("jump")
		elif can_double_jump and not double_jumping:
			double_jumping = true
			velocity.y = -jump_force
			audio.play_sound("jump")
			can_double_jump = false
			
	if on_floor:
		double_jumping = false
		if velocity.x != 0:
			new_anim = "run"
		else:
			new_anim = "idle"
	else:
		if velocity.y < 0:
			new_anim = "jumping"
		elif velocity.y >0:
			new_anim = "falling"

	if (new_anim != anim):
		anim = new_anim
		get_node("anim").play(anim)
			
	get_node("anim").set_speed(lerp(1, 2, abs(velocity.x/100))) 

	if (new_siding_left != siding_left):
		if (new_siding_left):
			get_node("sprite").set_scale(Vector2(-1, 1))
		else:
			get_node("sprite").set_scale(Vector2(1, 1))
		siding_left = new_siding_left
		
func _on_area_area_enter( area ):
	var name = area.name
	if name == "damage":
		apply_damage(null, null)
	elif name == "jump":
		can_double_jump = true
	elif name == "portal":
		area._on_portal_area_enter(get_node("area"))
	elif name == "water":
		area._on_water_area_enter(get_pos())
		velocity.y = 20
		in_water = true
	elif name == "door":
		if area.active:
			if !area.locked:
				global.next_level(area.next_level_id, area.next_zone_id)
				audio.play_sound("finish_level")
			elif area.locked:
				if !has_key:
					audio.play_sound("denied")
					return
				else:
					use_key()
					area.get_node("sprite").set_frame(0)
					global.next_level(area.next_level_id, area.next_zone_id)
					audio.play_sound("finish_level")
	elif name == "coin":
		global.update_score(area.amount)
		area.collect()
	elif name == "key":
		has_key = true
		area.collect()
		get_node("sprite/key").show()
	elif name == "hut":
		collect_hut(area.hut)
		area.collect()
	elif name == "sign":
		area.show_hint()
		
func collect_hut(f):
	get_node("sprite/hut").set_frame(f)
	
func use_key():
	get_node("sprite/key").hide()
	has_key = false
	
func _on_area_area_exit( area ):
	if area.name == "sign":
		area.hide_hint()
	elif area.name == "water":
		velocity.y = - water_out_jump_force
		area._on_water_area_exit(get_pos())
		in_water = false
#	elif area.name == "door":
#		if !area.active:
#			area.active = true

func apply_damage(damage, direction ):
	if !is_dead:
		is_dead = true
		die()
		
func die():
	var explosion = explosion_scene.instance()
	explosion.set_pos(get_pos())
	get_parent().add_child(explosion)
	set_fixed_process(false)
	get_node("anim").play("death")
	get_node("sprite").hide()
	get_node("sprite/hut").set_frame(0)
	use_key()
	global.restart()
	
func resurrect():
	get_node("anim").play("idle")
	get_node("sprite").show()
	set_fixed_process(true)
	is_dead = false
		
func rebound():
	if Input.is_action_pressed("ui_up"):
		velocity.y = -240
	else:
		velocity.y = -160
		
func _on_sprite_frame_changed():
	if get_node("sprite/hut").get_frame() == 0:
		get_node("sprite/hut").hide()
	else:
		get_node("sprite/hut").show()
			
func _ready():
	set_fixed_process(true)
	global.player = self
	pass


