class_name DialogueAction

const _TextboxGd = preload("res://ui/component/DialogueTextbox.gd")
const _ChoiceBoxGd = preload("res://ui/component/DialogueChoiceBox.gd")

enum DialogueMode {
  CONVERSATION,  # blocks movement, player advances
  NARRATION,     # non-blocking, player advances
  AMBIENT,       # non-blocking, timed auto-advance
}

static func dialogueCallable(params:Dictionary) -> int:
  assert(params.has('basePath'))
  var basePath:String = params['basePath']
  var title:String = params.get('title', 'start')
  var extraStates:Array = params.get('extraStates', [])
  var mode:DialogueMode = params.get('mode', DialogueMode.CONVERSATION)

  var resource:DialogueResource = _loadLocaleResource(basePath)
  assert(resource != null, "DialogueAction: could not load resource for path: " + basePath)

  if mode == DialogueMode.CONVERSATION:
    UI.activeConversation = true

  var advancementMode:int = (
    _TextboxGd.AdvancementMode.TIMED
    if mode == DialogueMode.AMBIENT
    else _TextboxGd.AdvancementMode.PLAYER
  )

  var line:DialogueLine = await DialogueManager.get_next_dialogue_line(resource, title, extraStates)
  while line != null:
    var entity:Entity = OVERWORLD.getEntityByDialogueName(line.character)

    var textbox = _TextboxGd.SCENE.instantiate()
    UI.chatBoxContainer.add_child(textbox)
    textbox.setup(line, entity, advancementMode)
    await textbox.dismissed

    var allowedResponses:Array = line.responses.filter(func(r): return r.is_allowed)
    if allowedResponses.size() > 0:
      var playerEntity:Entity = OVERWORLD.getPlayerEntity()
      var choiceBox = _ChoiceBoxGd.SCENE.instantiate()
      UI.chatBoxContainer.add_child(choiceBox)
      choiceBox.setup(line.responses, playerEntity)
      var chosen:DialogueResponse = await choiceBox.chosen
      line = await DialogueManager.get_next_dialogue_line(resource, chosen.next_id, extraStates)
    else:
      line = await DialogueManager.get_next_dialogue_line(resource, line.next_id, extraStates)

  if mode == DialogueMode.CONVERSATION:
    UI.activeConversation = false

  return Cutscene.CUTSCENE_CONTINUE

static func _loadLocaleResource(basePath:String) -> DialogueResource:
  var lang:String = TranslationServer.get_locale().left(2)
  var localePath:String = basePath + "." + lang + ".dialogue"
  if ResourceLoader.exists(localePath):
    return load(localePath)
  var fallback:String = basePath + ".en.dialogue"
  if ResourceLoader.exists(fallback):
    return load(fallback)
  return null

static func getDialogueCallable(basePath:String, title:String = "start", extraStates:Array = [], mode:DialogueMode = DialogueMode.CONVERSATION) -> Dictionary:
  return {
    "function": dialogueCallable,
    "basePath": basePath,
    "title": title,
    "extraStates": extraStates,
    "mode": mode,
  }
