# See https://github.com/OdyseeTeam/commentron/tree/master/commentapi for the
# comment API

class_name Comment
extends HBoxContainer

signal wants_replies
signal channel_pressed

var _comment_data: Dictionary = {}
var _resolved_channel_data: Dictionary = {}
# First page number is 1
# Should only be modified by comments.gd using
# `increment_last_replies_page_loaded()` when it loads another page of replies
var _last_replies_page_loaded: int = 0
var _default_thumbnail := ImageTexture.new()
var _initialized: bool = false
var _async_helper := AsyncHelper.new(self)
onready var _channel_button: ButtonContainer = find_node("ChannelButton")
onready var _channel_card: ChannelCard = find_node("ChannelCard")
onready var _timestamp_node: RichTextLabel = find_node("Timestamp")
onready var _comment_node: RichTextLabel = find_node("Comment")
onready var _reply_button: Button = find_node("ReplyButton")
onready var _like_button: ButtonContainer = find_node("LikeButton")
onready var _like_button_label: Label = find_node("LikeButtonLabel")
onready var _dislike_button: ButtonContainer = find_node("DislikeButton")
onready var _dislike_button_label: Label = find_node("DislikeButtonLabel")
onready var _show_replies_button: Button = find_node("ShowRepliesButton")
onready var _show_more_replies_button: Button = \
		find_node("ShowMoreRepliesButton")
onready var _replies_container: HBoxContainer = find_node("RepliesContainer")
onready var _replies_node: VBoxContainer = find_node("Replies")
onready var _thread_line_node: Control = find_node("ThreadLine")


func init(comment_data: Dictionary) -> void:
	_comment_data = comment_data
	_initialized = true


func _ready() -> void:
	if not _initialized:
		push_error("Object not initialized")
		return
	
	yield(_fetch_channel_data(), "completed")
	
	_show_replies_button.connect(
			"toggled", self, "_on_ShowRepliesButton_toggled")
	_show_more_replies_button.connect(
			"pressed", self, "_on_ShowMoreRepliesButton_pressed")
	_thread_line_node.connect("pressed", self, "_hide_replies")
	_channel_button.connect("pressed", self, "_on_ChannelButton_pressed")
	
	_setup()


func get_marker_y_position() -> int:
	"""
	Returns:
		The global position the marker should be at for this Comment along the
		parent Comment's thread line
	"""
	var y := int(
			_channel_card.get_global_position().y
			+ _channel_card.get_size().y / 2)
	return y


func get_last_replies_page_loaded() -> int:
	return _last_replies_page_loaded


func increment_last_replies_page_loaded() -> void:
	_last_replies_page_loaded += 1


func get_comment_id() -> String:
	return _comment_data.get("comment_id", "")


func add_replies(replies: Array) -> void:
	"""
	Displays the given replies to the current comment and disables the button
	to show more replies if all the replies are shown
	
	Args:
		replies: Array of Comment objects
	"""
	for reply in replies:
		_replies_node.add_child(reply)
	
	_thread_line_node.draw_thread_line(_replies_node.get_children())
	
	if _comment_data.get("replies", -1) <= _replies_node.get_child_count():
		# Hide the button if all replies have been loaded
		_show_more_replies_button.set_visible(false)
	else:
		_show_more_replies_button.set_visible(true)
	
	_show_more_replies_button.set_disabled(false)


func _fetch_channel_data() -> void:
	""" Fetches and stores resolved channel data """
	var tracker: Dictionary = \
			_async_helper.connect_wrapped(get_tree(), "idle_frame", false)
	yield(_async_helper.wait_until_finished([tracker]), "completed")
	
	if _comment_data.has("channel_url"):
		tracker = _async_helper.connect_wrapped(
				SDK.resolve([_comment_data["channel_url"]]), "completed")
		yield(_async_helper.wait_until_finished([tracker]), "completed")
		var resolve_response: Dictionary = tracker["result"]
		
		if (
				resolve_response.has("result")
				and len(resolve_response["result"].keys()) > 0
		):
			if resolve_response["result"].get(
					resolve_response["result"].keys()[0]) is Dictionary:
				_resolved_channel_data = resolve_response["result"].get(
						resolve_response["result"].keys()[0])


func _setup() -> void:
	var timestamp: int = _comment_data.get("timestamp", -1)
	var timestamp_text: String = \
			Helpers.parse_timestamp_to_relative_string(timestamp)
	var comment: String = _comment_data.get("comment", "")
	var like_count: int = _comment_data \
			.get("others_reactions", {}) \
			.get("like", 0)
	var dislike_count: int = _comment_data \
			.get("others_reactions", {}) \
			.get("dislike", 0)
	var reply_count: int = _comment_data.get("replies", 0)
	
	_channel_card.init(_resolved_channel_data.get("short_url", ""))
	_timestamp_node.set_text(timestamp_text)
	_comment_node.set_text(comment)
	_like_button_label.set_text("%d" % like_count)
	_dislike_button_label.set_text("%d" % dislike_count)
	_show_replies_button.set_visible(true if reply_count > 0 else false)


func _show_replies() -> void:
	_replies_container.set_visible(true)
	_thread_line_node.set_visible(true)
	_show_replies_button.set_text("Hide replies")
	if not _show_replies_button.is_pressed():
		_show_replies_button.set_pressed(true)


func _hide_replies() -> void:
	_replies_container.set_visible(false)
	_thread_line_node.set_visible(false)
	_show_replies_button.set_text("Show replies")
	if _show_replies_button.is_pressed():
		_show_replies_button.set_pressed(false)


func _on_ChannelButton_pressed() -> void:
	var channel_url: String = _resolved_channel_data.get("short_url", "")
	if channel_url != "":
		emit_signal("channel_pressed", channel_url)


func _on_ShowRepliesButton_toggled(button_pressed: bool) -> void:
	if button_pressed:
		_show_replies()
		if _last_replies_page_loaded == 0:
			emit_signal("wants_replies")
	else:
		_hide_replies()


func _on_ShowMoreRepliesButton_pressed() -> void:
	_show_more_replies_button.set_disabled(true)
	emit_signal("wants_replies")
