extends Node

var actors = []

var ready = true
var inventory = []

var db_dialogues = []
var db_quests = []
var db_actors = []
var db_items = []

var interlocutor = null
var selector = -1
var quest_id = -1
var responses = []
var next_dialogue = -1
var cancel = false
var event = []
var quest = {}
var actor_method = {}

var active_quests = []

func get_dialogue(id):
	for d in db_dialogues:
		if d["id"] == id:
			return d
	return db_dialogues[0]

func get_quest(id):
	for q in db_quests:
		if q["id"] == id:
			return q
			
func get_actor(id):
	for a in db_actors:
		if a["id"] == id:
			return a
			
func get_item_data(_name):
	for i in db_items:
		if i["name"] == _name:
			return i
			
func get_actor_data(id):
	return db_actors[id]
	
func start_dialogue(id, i):
	next_dialogue = id
	interlocutor = i
	interlocutor.on_start_dialogue()
	check_quests()
	dialogue_handler()
	
func check_quests():
	if !active_quests.empty():
		var to_remove = []
		for n in active_quests.size():
			if active_quests[n]["expectant"] == interlocutor:
				if active_quests[n]["completed"]:
					var completed = active_quests[n]
					for o in completed["body"]["objectives"]:
						if o["category"] == "gather":
							remove_from_inventory(completed["slot_id"], o["required"])
					next_dialogue = completed["body"]["on_complete_dialogue_id"]
					take_reward(completed["body"]["rewards"][0])
					var triggers = active_quests[n]["body"]["triggers"]
					if !triggers.empty():
						for t in triggers:
							_signal(t)
					to_remove.append(n)
					interlocutor.on_complete_the_quest()
				else:
					next_dialogue = active_quests[n]["body"]["wait_dialogue_id"]
		quest_complete(to_remove)
	
func _signal(t):
	pass
	
func cancel_dialogue():
	var method = ""
	Global.gui.ui_hide_dialogue_box()
	Global.player.in_dialogue = false
	interlocutor.on_cancel_dialogue()
	interlocutor = null
	selector = -1
	next_dialogue = -1
	quest = {}
	cancel = false
	quest_id = -1
	if !actor_method.empty():
		for a in actors:
			if a["actor_id"] == actor_method["actor_id"]:
				a["body"].call_deferred(actor_method["method"], actor_method["args"])
		actor_method = {}
	responses = []
	
func dialogue_handler():
	var text = ""
	var next = []
	var arrow
	var dialogue
	var conversing
	var text_anim = false
	
	if cancel:
		cancel_dialogue()
		return
		
	if !actor_method.empty():
		for a in actors:
			if a["actor_id"] == actor_method["actor_id"]:
				a["body"].call_deferred(actor_method["method"], actor_method["args"])
		actor_method = {}
		
	if quest_id >= 0 and selector < 0 and next_dialogue < 0:
		quest = get_quest(quest_id)
		text = quest["description"] + "\n"
		selector = -1
		responses = quest["responses"]
		arrow = true	
	if selector >= 0:
		dialogue = responses[selector]
		next = dialogue["next"]
		arrow = true
		selector = -1
	elif next_dialogue >= 0:
		dialogue = get_dialogue(next_dialogue)
		text = dialogue["text"]
		next = dialogue["next"]
		arrow = true
		next_dialogue = -1
		conversing = true
		text_anim = true
	elif !responses.empty():
		if text == "":
			text = "Варианты ответа: \n"
		for r in responses:
			text += r["text"] + "\n"
		arrow = false
		selector = 0
		conversing = false
	if !next.empty():
		for a in next:
			if a == "cancel":
				cancel = true
			if a == "game_event":
				event = [dialogue["game_event"], dialogue["game_event_param"]]
				events_handler(event)
			if a == "give_item":
				var items = dialogue["items"]
				Global.player.pick_up_items(items)
			if a == "response":
				responses = dialogue["responses"]
			if a == "give_quest":
				quest_id = get_actor(interlocutor.id)["quests"][0]
			if a == "take_quest":
				var result = take_quest(quest)
				if result[0]:
					next_dialogue = quest["on_complete_dialogue_id"]
					take_reward(quest["rewards"][0])
					dialogue_handler()
					remove_from_inventory(result[1], quest["objectives"][0]["required"])
					Audio.play_sound("quest_complete", false)
			if a == "next_sentence":
				next_dialogue = dialogue["next_dialogue"]
			elif a == "next_dialogue":
				next_dialogue = dialogue["next_dialogue"]
				dialogue_handler()
				return
	
	interlocutor.on_conversing(conversing)
	Global.gui.ui_set_selector(selector)
	Global.gui.ui_show_dialogue_box(text, arrow, text_anim)
	
func events_handler(event):
	if event[0] == "call_actor_method":
		actor_method = {args = event[1][2], actor_id = event[1][1], method = event[1][0]}
	
func take_quest(q):
	var progress = 0	
	var objectives = q["objectives"]
	
	for o in objectives:
		for i in inventory:
			if i["body"]["name"] == o["object_name"]:
				if i["number"] >= o["required"]:
					return [true, i["id"]]
				else:
					o["progress"] = i["number"]
	active_quests.append({completed = false, body = q, expectant = interlocutor, slot_id = -1})
	quest_id = -1
	Global.gui.ui_quest_list(active_quests)
	Audio.play_sound("take_a_task", false)
	return [false, null]
	
func check_objective(event, object_name, id):
	if !active_quests.empty():
		for a in active_quests:
			var objectives = a["body"]["objectives"]
			for o in objectives:
				if o["object_name"] == object_name:
					o["progress"] += 1
					if o["progress"] >= o["required"]:
						a["completed"] = true
						a["expectant"].on_task_completed()
						if o["category"] == "gather":
							a["slot_id"] = id
		Global.gui.ui_quest_list(active_quests)
					
func quest_complete(indexes):
	for i in indexes:
		active_quests.remove(i)
		Audio.play_sound("quest_complete", false)
	Global.gui.ui_quest_list(active_quests)
	
		
func change_selector(changer):
	if selector >= 0:
		selector = fposmod(selector + changer, responses.size())
		Global.gui.ui_set_selector(selector)
	
func load_dialogues():
	var file = File.new()
	file.open("res://db/dialogues.json", file.READ)
	var text = file.get_as_text()
	var json = parse_json(text)
	db_dialogues = json["dialogues"]
		
func load_quests():
	var file = File.new()
	file.open("res://db/quests.json", file.READ)
	var text = file.get_as_text()
	var json = parse_json(text)
	db_quests = json["quests"]
	
func load_actors():
	var file = File.new()
	file.open("res://db/actors.json", file.READ)
	var text = file.get_as_text()
	var json = parse_json(text)
	db_actors = json["actors"]
	
func load_items():
	var file = File.new()
	file.open("res://db/items.json", file.READ)
	var text = file.get_as_text()
	var json = parse_json(text)
	db_items = json["items"]

func is_ready(state):
	ready = state
	if interlocutor != null:
		interlocutor.on_conversing(!state)
		
func take_reward(rewards):
	var items = rewards["items"]
	if items.size() > 0:
		for i in items:
			add_to_inventory(i)
	Global.player.add_exp(rewards["exp"])
		
func add_to_inventory(item_name):
	var slot_id
	var added = false
	var item_data = {}
	if !inventory.empty():
		for i in inventory:
			if i["body"]["name"] == item_name:
				i["number"] += 1
				added = true
				slot_id = i["id"]
	if !added:
		item_data = get_item_data(item_name)
		randomize()
		var rnd = randi() % 999999
		slot_id = rnd
		inventory.append({id = slot_id, body = item_data, number = 1})
	check_objective("collect", item_name, slot_id)
	Global.gui.ui_inventory(inventory)
	return item_data
	
func remove_from_inventory(id, number):
	print(inventory)
	for i in inventory:
		if i["id"] == id:
			inventory.erase(i)
			print(inventory)
	Global.gui.ui_inventory(inventory)
	
	
func use_item(slot_id):
	var item = inventory[slot_id]["body"]
	var result = Global.player.use_item(item)
	if result == "use_up":
		remove_from_inventory(inventory[slot_id]["id"], 1)
	
func _ready():
	load_dialogues()
	load_quests()
	load_actors()
	load_items()
