extends Node

class Prompt extends RefCounted:
	var _text := ""
	var _choiceIDs : Array[int]

	static func construct(
		text : String,
		choiceIDs : Array[int]
	) -> Prompt:
		
		if !text or !choiceIDs:
			push_error("Incomplete construction params. Could not create prompt.")
			return null

		var instance := Prompt.new()
		instance._text = text
		instance._choiceIDs = choiceIDs
		return instance

	func get_text() -> String:
		return _text

	func get_choice_ids() -> Array[int]:
		return _choiceIDs

class Choice extends RefCounted:
	var _text := ""
	var _promptID := -1
	var _unlockMap := {
		"choiceID" : -1,
		"promptID" : -1
	}
	var _sadnessVal := 0
	var _joyVal := 0

	static func construct(
		text : String,
		promptID : int,
		sadnessVal := 0,
		joyVal := 0,
		unlockChoiceID := -1,
		unlockPromptID := -1
	) -> Choice:
	
		var incompleteUnlockMap := (
			unlockChoiceID == -1 and unlockPromptID != -1 or
			unlockChoiceID != -1 and unlockPromptID == -1
		)
		if incompleteUnlockMap:
			push_error("Incomplete unlock map. Unable to create choice.")
			return null

		#print(promptID)
		if !text or promptID == -1:
			push_error("Incomplete construction params. Could not create choice.")
			return null

		var instance := Choice.new()
		instance._text = text
		instance._promptID = promptID
		instance._unlockMap.choiceID = unlockChoiceID
		instance._unlockMap.promptID = unlockPromptID
		instance._joyVal = joyVal
		instance._sadnessVal = sadnessVal
		return instance

	func get_joy_val() -> int:
		return _joyVal

	func get_sadness_val() -> int:
		return _sadnessVal

	func get_unlock_map() -> Dictionary:
		return _unlockMap

	func get_text() -> String:
		return _text

	func get_prompt_id() -> int:
		return _promptID

static var promptMap : Dictionary[int, Prompt]
static var choiceMap : Dictionary[int, Choice]

func initialize() -> void:
	_create_prompt(
		0,
		"Ladies and Gentlemen, skinny and stout,
I'll tell you a tale I know nothing about;
The Admission is free, so pay at the door,
Now pull up a chair and sit on the floor.",
		[0]
	)
	_create_prompt(
		1,
		"And they... Begging your pardon, I seemed to have gotten it wrong. Ahem.",
		[0]
	)
	_create_prompt(
		2,
		"One fine day in the middle of the night",
		[3, 1, 2]
	)
	_create_prompt(
		3,
		"Two dead boys got up to fight",
		[4, 5]
	)
	_create_prompt(
		4,
		"Back to back they faced each other",
		[5]
	)
	_create_prompt(
		5,
		"Drew their swords and shot each other",
		[6]
	)
	_create_prompt(
		6,
		"A blind man came to watch fair play",
		[8, 9]
	)
	_create_prompt(
		7,
		"A mute man came to shout “Horray!",
		[10]
	)
	_create_prompt(
		8,
		"A deaf policeman heard the noise and
Came to stop those two dead boys.",
		[11]
	)
	_create_prompt(
	9,
	"He lived on the corner in the middle of the block,",
	[14, 15, 13]
	)
	_create_prompt(
	10,
	"In a two-story house on a vacant lot,",
	[16]
	)
	_create_prompt(
	11,
	"A man with no legs came walking by,
	and kicked the lawman in his thigh.",
	[17]
	)
	_create_prompt(
	12,
	"And that's all the stories I have today. Callooh Callay o' Frabjuous day!",
	[18]
	)
	# _create_prompt(1, "I’ll tell you a tale I know nothing about...", [1])
	# _create_prompt(2, "The Admission is free, so pay at the door,", [2])
	# _create_prompt(3, "Now pull up a chair and sit on the floor.", [3])

	_load_choice_data()

func _load_choice_data() -> void:
	const CHOICE_DATA_PATH := "res://scriptables/choice_data/"
	var dir := DirAccess.open(CHOICE_DATA_PATH)

	if dir == null:
		push_error("Failed to open dir: %s" % CHOICE_DATA_PATH)
		return

	dir.list_dir_begin()
	var fileName := dir.get_next()

	while fileName != "":
		if not dir.current_is_dir() and fileName.ends_with(".tres"):
			var fullPath := CHOICE_DATA_PATH.path_join(fileName)
			var res := load(fullPath)

			if res and res is ChoiceData:
				_create_choice(
					res.id,
					res.text,
					res.promptID,
					res.sadnessVal,
					res.joyVal,
					res.unlockChoiceID,
					res.unlockPromptID
				)

		fileName = dir.get_next()

	dir.list_dir_end()

func _create_prompt(
	id : int,
	text : String,
	choiceIDs : Array[int]
) -> void:
	promptMap[id] = Prompt.construct(text, choiceIDs)

func overwrite_prompt_choices(id:int, choiceIDs:Array[int]) -> void:
	var currentPrompt := promptMap[id]
	if !currentPrompt:
		push_error("Attempting to overwrite nonexistent prompt: ")
		return

	var choicesToAdd := choiceIDs.duplicate()
	for choiceID in choiceIDs:
		if choicesToAdd.has(choiceID):
			continue
		choicesToAdd.append(choiceID)

	var text := currentPrompt.get_text()
	_create_prompt(id, text, choiceIDs)

func _create_choice(
	id : int,
	text : String,
	promptID : int,
	sadnessVal := 0,
	joyVal := 0,
	unlockChoiceID : int = -1,
	unlockPromptID : int = -1
) -> void:
	if id == -1:
		push_error("No ID assigned to choice. Failed to create")
		return

	if choiceMap.has(id):
		push_error("Duplicate ID detected: ", id)
		return

	# print("Unlock choice ID: ", unlockChoiceID)
	# print("Unlock prompt ID: ", unlockPromptID)
	choiceMap[id] = Choice.construct(
		text,
		promptID,
		sadnessVal,
		joyVal,
		unlockChoiceID,
		unlockPromptID
	)

func get_prompt(id:int) -> Dictionary:
	var data := {}
	var prompt := promptMap[id]
	data.text = prompt.get_text()
	data.choiceIDs = prompt.get_choice_ids()
	return data

func get_choice(id:int) -> Dictionary:
	var data := {}
	var choice := choiceMap[id]
	data.text = choice.get_text()
	data.promptID = choice.get_prompt_id()
	data.unlockMap = choice.get_unlock_map()
	data.sadness = choice.get_sadness_val()
	data.joy = choice.get_joy_val()
	return data
