extends Spatial
var loading

func new_quest(q):
	var title = q.get_title()
	var desc = q.get_description()
	print("title: ", title)
	print("desc: ", desc)
func _ready():
	loading = preload("res://ui/loading.tscn").instance()
	get_tree().get_root().add_child(loading)

	var e = $"meta-ai".connect("spawn_player", self, "spawn_player")
	assert(e == OK)
	e = $"meta-ai".connect("spawn_npc", self, "spawn_npc")
	assert(e == OK)
#	$cam_target/offset/Camera.set_as_toplevel(true)
	global.set_save_slot(0)
	e = $dungeon.connect("prepared", self, "start_ai")
	assert(e == OK)
	e = quests.connect("new_quest", self, "new_quest")
	assert(e == OK)
	global.interior = $dungeon

var default_meta = {
	"grabbing": false,
	"grabbed": false,
	"smart_object": false,
	"weapon": false,
	"busy": false,
	"action": "",
}
var player_meta = {
	"health": 1000,
	"max_health": 1000,
	"stamina": 500,
	"max_stamina": 500,
}

func start_ai():
	print("prepared")
	$"meta-ai".start()
	global.interior = $dungeon
	quests.activate()

func save():
	global.save_characters()
	$dungeon.save()
	quests.save()
	global.save_game()

func spawn_player(spawner):
	print("spawned player")
	loading.queue_free()
	var player_sc = load("res://scenes/characters/male.tscn")
	var player = player_sc.instance()
	add_child(player)
	player.global_transform = spawner.global_transform.translated(Vector3(randf() * 0.4, 0.0, randf() * 0.4))
#	print("spawn player at: ", player.global_transform.origin)
	global.player = player
	$cam_target.global_transform.origin = player.global_transform.origin
	rpg.create_stats(player)
	for k in default_meta.keys():
		player.set_meta(k, default_meta[k])
	player.name = "player"
	combat.register(player)
	player.set_meta("spawner", spawner)
	player.add_to_group("player")
	$cam_target/cam_rot/offset/Camera.current = true
	global.start_time()
func spawn_npc(spawner):
	var npc
	var g
	if spawner.is_in_group("male"):
		var npc_sc = load("res://scenes/characters/male.tscn")
		var male_hair = preload("res://scenes/characters/hair1-male/male_g_2018-short02.mesh")
		npc = npc_sc.instance()
		var hair = npc.get_skeleton().get_node("hair")
		hair.mesh = male_hair
		g = "male"
	elif spawner.is_in_group("female"):
		var npc_sc = load("res://scenes/characters/female.tscn")
		npc = npc_sc.instance()
		g = "female"
	add_child(npc)
	for k in spawner.get_groups():
		if k == "spawn":
			continue
		npc.add_to_group(k)
	spawner.set_meta("npc", npc)
	npc.set_meta("spawner", spawner)
	npc.name = "npc_" + g + "_" + str(get_tree().get_nodes_in_group("npc").size())
	npc.global_transform = spawner.global_transform.translated(Vector3(randf() * 0.4, 0.0, randf() * 0.4))
	npc.add_to_group("npc")
	if spawner.has_meta("stats"):
		var stats = spawner.get_meta("stats")
		for k in stats.keys():
			npc.set_meta(k, stats[k])
	else:
		rpg.create_stats(npc)
	for k in default_meta.keys():
		npc.set_meta(k, default_meta[k])
	var bb = Blackboard.new()
	npc.add_child(bb)
	bb.name = "blackboard"
	combat.register(npc)
	if npc.is_in_group("guard"):
		var guard_suit = preload("res://scenes/characters/guard.escn")
		var guard_suit_i = guard_suit.instance()
		var skel = npc.get_skeleton()
		for k in guard_suit_i.get_node("male_g_2018").get_children():
			if k is MeshInstance:
				k.get_parent().remove_child(k)
				skel.add_child(k)
				k.owner = skel.owner
		guard_suit_i.queue_free()
	if npc.is_in_group("maid"):
		var maid_suit = preload("res://scenes/characters/maid.escn")
		var maid_suit_i = maid_suit.instance()
		var skel = npc.get_skeleton()
		for k in maid_suit_i.get_node("female").get_children():
			if k is MeshInstance:
				k.get_parent().remove_child(k)
				skel.add_child(k)
				k.owner = skel.owner
#		npc.skirt_simulation(true)
		maid_suit_i.queue_free()

func can_control():
	if global.player.get_meta("smart_object"):
		return false
	elif global.player.get_meta("busy"):
		return false
	return true

var mouse_motion: Vector2 = Vector2()
func _unhandled_input(event):
	if event is InputEventMouseMotion:
		mouse_motion += event.relative

var cam_fixup_cooldown = 0.0
var ai_debug: Node
func _process(delta):
	if Input.is_action_just_pressed("ai_debug"):
		if !ai_debug:
			var aid = load("res://scenes/debug/ai_debug.tscn")
			ai_debug = aid.instance()
			add_child(ai_debug)
		else:
			ai_debug.queue_free()
			ai_debug = null
	if global.player:
		var player_xform = global.player.global_transform
#		$cam_target.rotate(Vector3(0, 1, 0), 0.2 * delta)
		$cam_target.global_transform.origin = $cam_target.global_transform.origin.linear_interpolate(global.player.global_transform.origin, delta)
#		$cam_target/offset/Camera.look_at($cam_target/offset.global_transform.origin, Vector3(0, 1, 0))
		var cam_xform = $cam_target/cam_rot/offset/Camera.global_transform
		cam_xform.basis[0].y = 0
		cam_xform.basis[0] = cam_xform.basis[0].normalized()
		cam_xform.basis[2].y = 0
		cam_xform.basis[2] = cam_xform.basis[2].normalized()
		var up = Vector3(0, 1, 0)
		cam_xform.basis[1] = up
		cam_xform = cam_xform.orthonormalized()
		var lookat_xform_left = player_xform.looking_at(player_xform.origin - cam_xform.basis[0], up)
		var lookat_xform_right = player_xform.looking_at(player_xform.origin + cam_xform.basis[0], up)
		var lookat_xform_forward = player_xform.looking_at(player_xform.origin - cam_xform.basis[2], up)
		var lookat_xform_back = player_xform.looking_at(player_xform.origin + cam_xform.basis[2], up)
		var player_fwd = player_xform.basis[2]
		var cam_fwd = cam_xform.basis[2]
		var walking = false
		if abs(mouse_motion.x) > 0.1:
			$cam_target.rotate_y(-mouse_motion.x * 0.7 * delta)
			cam_fixup_cooldown += 2.0 * delta
			if cam_fixup_cooldown > 10.0:
				cam_fixup_cooldown = 10.0
		mouse_motion.x = 0.0
		if abs(mouse_motion.y) > 0.1:
			$cam_target/cam_rot.rotate_x(mouse_motion.y * 0.3 * delta)
			$cam_target/cam_rot.rotation.x = clamp($cam_target/cam_rot.rotation.x, -PI / 3.0, PI / 3.0)
		mouse_motion.y = 0.0
		if can_control():
			if Input.is_action_pressed("walk_forward"):
				global.player.orientation.basis = lookat_xform_forward.basis
				global.player.do_walk()
				global.player.set_walk_speed(2.5)
				walking = true
			if Input.is_action_pressed("walk_left"):
				global.player.orientation.basis = lookat_xform_left.basis
				global.player.do_walk()
				global.player.set_walk_speed(1.5)
				walking = true
			if Input.is_action_pressed("walk_right"):
				global.player.orientation.basis = lookat_xform_right.basis
				global.player.do_walk()
				walking = true
				global.player.set_walk_speed(1.5)
			if Input.is_action_pressed("walk_back"):
				global.player.orientation.basis = lookat_xform_back.basis
				global.player.do_walk()
				walking = true
				global.player.set_walk_speed(1.5)
			if Input.is_action_pressed("grab"):
				if !global.player in global.smart_object:
					var close = []
					var xform: Transform = global.player.global_transform
					for k in get_tree().get_nodes_in_group("npc"):
						if k.get_meta("smart_object"):
							print(k.name, " in smart object")
							continue
						var npc_pos = k.global_transform.origin
						if xform.origin.distance_to(npc_pos) < 2.0:
							if xform.xform_inv(npc_pos).z < 0.0:
								close.push_back(k)
					var dst = INF
					var best = null
					for k in close:
						var npc_pos = k.global_transform.origin
						var xpos = xform.xform_inv(npc_pos)
						if dst > xpos.length():
							dst = xpos.length()
							best = k
					if best:
						print("grabbing ", best.name)
						if !global.player.get_meta("grabbing"):
							grabbing.grab_character(global.player, best)
				else:
					print("smart object!! ", global.smart_object, " ", global.player)
			if Input.is_action_pressed("attack"):
				global.player.do_attack()
		if can_control():
			if !walking:
				global.player.do_stop()
				if cam_fixup_cooldown <= 0.0 && global.player && abs(global.player.velocity.z) > 0.001:
					var v1 = Vector2(player_fwd.x, player_fwd.z)
					var v2 = Vector2(cam_fwd.x, cam_fwd.z)
					var angle = v2.angle_to(v1)
					if abs(angle) > 0.1:
						$cam_target.rotate_y(-angle * delta)
				else:
					cam_fixup_cooldown -= delta
		if Input.is_action_just_pressed("save_game"):
			save()
