extends KinematicBody2D

export (bool) var interactive = true
export(float) var move_speed = 200.0
export (int) var max_speed = 200
export (float) var acceleration = 15
export (float, 0, 1.0) var friction = 0.1

onready var world = get_parent()
onready var tile_map = get_parent().get_node("TileMap")
onready var tile_map_bg = get_parent().get_node("TileMapBg")
onready var freeze_camera_sound = $FreezeCameraSound
onready var unfreeze_camera_sound = $UnfreezeCameraSound

var separation = 2

var camera = null
var camera_frozen = false
var other_player = null
var frozen_view = null
var frozen_view_sprite = null
var frozen_view_sprite_bg = null
var frozen_colliders = null
var frozen_image = null
var frozen_image_width = 600
var frozen_image_height = 300 + separation/2
var frozen_image_texture = null
var viewport_container_both = null
var split_line = null
var press_enter = null

var is_complete = false
var velocity = Vector2.ZERO
var direction = 1
var float_time = 0
var return_position = null

func reset():
	is_complete = false
	velocity = Vector2.ZERO
	direction = 1
	float_time = 0
	return_position = null

var is_tile_map_cached = false
func _physics_process(delta):
	if not is_tile_map_cached and tile_map and tile_map_bg:
		render_frozen_tile_map([tile_map_bg, tile_map])
		is_tile_map_cached = true
		# other_player.frozen_image = frozen_image
		# other_player.is_tile_map_cached = true

	if not is_tile_map_cached:
		# world.visible = false
		# if frozen_view:
		# 	frozen_view.visible = false
		return

	# world.visible = true
	# if frozen_view:
	# 	frozen_view.visible = true

	if interactive:
		if is_complete:
			$AnimatedSprite.play("complete")
			if Input.is_action_just_pressed("next_level"):
				var next_level = ProjectSettings.get("levels/next_level") + 1
				if next_level > 10:
					ProjectSettings.set("levels/next_level", 1)
					get_tree().change_scene("res://TitleScreen.tscn")
				else:
					ProjectSettings.set("levels/next_level", next_level)
					get_tree().change_scene("res://Level.tscn")
		else:
			handle_freeze_camera()
			handle_motion(delta)
			handle_animation(delta)
	else:
		handle_animation(delta)

func handle_freeze_camera():
	if Input.is_action_just_pressed("freeze_screen_1"):
		camera_frozen = not camera_frozen
		if camera_frozen:
			freeze_camera_sound.play()
			split_line.visible = false
			
			add_frozen_colliders()
			#render_frozen_view([tile_map_bg], frozen_view_sprite_bg)
			#render_frozen_view([tile_map], frozen_view_sprite)
			render_frozen_view([tile_map_bg, tile_map], frozen_view_sprite)
			camera.target = null
			
			frozen_view.transfer_object(self, Vector2(300, 150))
		else:
			unfreeze_camera_sound.play()
			split_line.visible = true
			
			camera.target = self
			frozen_view_sprite_bg.texture = null
			frozen_view_sprite.texture = null
			remove_frozen_colliders()
			
			frozen_view.return_object(self, world)
			if position.y <= 300:
				position = position - Vector2(300,150) + return_position
			else:
				var delta = other_player.return_position - Vector2(300, 450)
				position = position + delta

# func _ready():
# 	frozen_image = Image.new()
# 	frozen_image.create(frozen_image_width, frozen_image_height, false, Image.FORMAT_RGB8)
# 	frozen_image_texture = ImageTexture.new()

var min_int = -9223372036854775808
var max_int = 9223372036854775807
var min_position = Vector2(max_int, max_int)
var max_position = Vector2(min_int, min_int)
var cell_width = 32
var cell_height = 32

func render_frozen_tile_map(maps):
	for map in maps:
		var rect = map.get_used_rect()
		if rect.position < min_position:
			min_position = rect.position
		if rect.end > max_position:
			max_position = rect.end

	var image_width = (max_position.x - min_position.x) * cell_width
	var image_height = (max_position.y - min_position.y) * cell_height

	frozen_image = Image.new()
	frozen_image.create(image_width, image_height, false, Image.FORMAT_RGB8)
	frozen_image_texture = ImageTexture.new()

	for map in maps:
		# var cell_width = map.cell_size.x
		# var cell_height = map.cell_size.y
		for cell in map.get_used_cells():
			var tile_index = map.get_cell(cell.x, cell.y)
			var tile_texture = map.tile_set.tile_get_texture(tile_index)
			var tile_image = tile_texture.get_data()

			var autotile_cell = map.get_cell_autotile_coord(cell.x, cell.y)
			var offset_x = autotile_cell.x * cell_width
			var offset_y = autotile_cell.y * cell_height

			var dest_x = (cell.x * cell_width) - (min_position.x * cell_width)
			var dest_y = (cell.y * cell_height) - (min_position.y * cell_height)

			frozen_image.blit_rect(tile_image, Rect2(offset_x, offset_y, cell_width, cell_height), Vector2(dest_x, dest_y))

func render_frozen_view(maps, sprite):
	var image = Image.new()
	image.create(frozen_image_width, frozen_image_height, false, Image.FORMAT_RGB8)

	var offset_x = (300 - camera.position.x) + 0.5
	var offset_y = 150 - camera.position.y - (separation/4)
	offset_x = (-min_position.x * cell_width) - offset_x
	offset_y = (-min_position.y * cell_height) - offset_y

	image.blit_rect(frozen_image, Rect2(offset_x, offset_y, frozen_image_width, frozen_image_height), Vector2(0, 0))
	
	frozen_image_texture.create_from_image(image)
	sprite.texture = frozen_image_texture

func add_frozen_colliders():
	var cell_width = tile_map.cell_size.x
	var cell_height = tile_map.cell_size.y
	var half_cell_width = cell_width / 2
	var half_cell_height = cell_height / 2

	for cell in tile_map.get_used_cells():
		#var collider_x = (cell.x * cell_width) + half_cell_width
		#var collider_y = (cell.y * cell_height) + half_cell_height
		var collider_x = (cell.x * cell_width) + half_cell_width + 300 - camera.position.x
		var collider_y = (cell.y * cell_height) + half_cell_height + 150 - camera.position.y
		
		if collider_y - half_cell_height <= 300:
			var rect = RectangleShape2D.new()

			if collider_y + half_cell_height > 300:
				var sobra = collider_y + half_cell_height - 300
				var collider_height = cell_height - sobra + separation/2
				rect.set_extents(Vector2(half_cell_width, collider_height/2))
				collider_y = collider_y - sobra/2
			else:
				rect.set_extents(Vector2(half_cell_width, half_cell_height))

			var collider = CollisionShape2D.new()
			collider.shape = rect
			collider.translate(Vector2(collider_x, collider_y))
			frozen_colliders.add_child(collider)
			
			var light_occluder = LightOccluder2D.new()
			light_occluder.translate(Vector2(collider_x -half_cell_width , collider_y - half_cell_height))
			var occluder = OccluderPolygon2D.new()
			occluder.polygon = PoolVector2Array([Vector2(0,0), Vector2(cell_width,0), Vector2(cell_width,cell_height), Vector2(0,cell_height)])
			light_occluder.occluder = occluder
			frozen_colliders.add_child(light_occluder)

func remove_frozen_colliders():
	for collider in frozen_colliders.get_children():
		frozen_colliders.remove_child(collider)
		collider.queue_free()

func handle_motion(_delta):
	if Input.is_action_pressed("move_left_1"):
		velocity.x = max(velocity.x - acceleration, -max_speed)
		direction = -1
	elif Input.is_action_pressed("move_right_1"):
		velocity.x = min(velocity.x + acceleration, max_speed)
		direction = 1
	else:
		velocity.x = lerp(velocity.x, 0, friction)
	
	if Input.is_action_pressed("move_up_1"):
		velocity.y = max(velocity.y - acceleration, -max_speed)
	elif Input.is_action_pressed("move_down_1"):
		velocity.y = min(velocity.y + acceleration, max_speed)
	else:
		velocity.y = lerp(velocity.y, 0, friction)
	velocity = move_and_slide(velocity, Vector2.UP, false, 4, PI/4, false)

func handle_animation(delta):
	var freq = 5
	var amplitude = 4
	float_time += delta
	$AnimatedSprite.position.y = sin(float_time * freq) * amplitude
	
	$AnimatedSprite.play("idle")
	
	if direction == 1:
		$AnimatedSprite.flip_h = false
	elif direction == -1:
		$AnimatedSprite.flip_h = true

func _on_ConnectArea_area_entered(area):
	if area.name == "ConnectArea2" and not is_complete and not other_player.has_salt:
		is_complete = true
		split_line.visible = false
		viewport_container_both.visible = true
		$AnimatedSprite/Light2D.shadow_enabled = false
		$CompleteSound.play()
		
		yield(get_tree().create_timer(1.5), "timeout")
		
		$Tween.interpolate_property(self, "modulate", Color(1, 1, 1, 1), Color(1, 1, 1, 0), 1.0)
		$Tween.start()
		yield($Tween, "tween_all_completed")
		
		$AnimatedSprite/Light2D.energy = 0
		
		press_enter.visible = true

		# var next_level = ProjectSettings.get("levels/next_level")
		# ProjectSettings.set("levels/next_level", next_level + 1)
		# get_tree().change_scene("res://TitleScreen.tscn")
		
