extends Node

# State this scene should be initialized with
var _init_state: Dictionary = {}
var _async_helper := AsyncHelper.new(self)
onready var _claim_type: OptionButton = find_node("ClaimType")
onready var _stream_type_any: CheckBox = find_node("StreamTypeAny")
onready var _stream_type_video: CheckBox = find_node("StreamTypeVideo")
onready var _stream_type_image: CheckBox = find_node("StreamTypeImage")
onready var _stream_type_document: CheckBox = find_node("StreamTypeDocument")
onready var _duration_equality: OptionButton = find_node("DurationEquality")
onready var _duration: VSlider = find_node("Duration")
onready var _duration_text: Label = find_node("DurationText")
onready var _only_following: CheckButton = find_node("OnlyFollowing")
onready var _language: OptionButton = find_node("Language")


func _ready() -> void:
	_claim_type.connect("item_selected", self, "_on_ClaimType_item_selected")
	for stream_type \
			in [_stream_type_video, _stream_type_image, _stream_type_document]:
		stream_type.connect("toggled", self, "_on_StreamType_toggled")
	_duration.connect("value_changed", self, "_on_Duration_value_changed")
	
	_claim_type.add_item("Channel")
	_claim_type.add_item("Stream")
	_claim_type.add_item("Repost")
	_claim_type.add_item("Collection")
	
	_duration_equality.add_item(">")
	_duration_equality.add_item("<")
	
	if _init_state.empty():
		_setup()
	else:
		_setup_state()


func get_options() -> Dictionary:
	var options: Dictionary = {
		"claim_type": _get_claim_type(),
		"stream_types": _get_stream_types(),
		"duration": _get_duration(),
		"channel_ids": yield(_get_channel_ids(), "completed"),
	}
	if not _duration.is_editable():
		options.erase("duration")
	
	return options


func get_state() -> Dictionary:
	"""
	Returns:
		The data needed to restore the main changes made to this scene
	"""
	var state: Dictionary = {
		"ClaimType_selected": _claim_type.get_selected(),
		"StreamType_is_pressed": [
			_stream_type_any.is_pressed(),
			_stream_type_video.is_pressed(),
			_stream_type_image.is_pressed(),
			_stream_type_document.is_pressed(),
		],
		"DurationEquality_selected": _duration_equality.get_selected(),
		"Duration_value": _duration.get_value(),
		"OnlyFollowing_is_pressed": _only_following.is_pressed(),
		"Language_selected": _language.get_selected(),
	}
	return state


func set_state(state: Dictionary) -> void:
	"""
	Call before the node enters the SceneTree to initialize it with the given
	state
	"""
	_init_state = state


func _setup() -> void:
	_claim_type.select(1)
	_on_ClaimType_item_selected(0)


func _setup_state() -> void:
	""" Sets up the scene using the state description in `_init_state` """
	_claim_type.select(_init_state["ClaimType_selected"])
	
	_stream_type_any.set_pressed_no_signal(
			_init_state["StreamType_is_pressed"][0])
	_stream_type_video.set_pressed_no_signal(
			_init_state["StreamType_is_pressed"][1])
	_stream_type_image.set_pressed_no_signal(
			_init_state["StreamType_is_pressed"][2])
	_stream_type_document.set_pressed(_init_state["StreamType_is_pressed"][3])
	
	_duration_equality.select(_init_state["DurationEquality_selected"])
	_duration.set_value(_init_state["Duration_value"])
	
	_only_following.set_pressed(_init_state["OnlyFollowing_is_pressed"])
	
	_language.select(_init_state["Language_selected"])


func _get_claim_type() -> String:
	return _claim_type.get_item_text(_claim_type.get_selected()).to_lower()


func _get_stream_types() -> Array:
	var stream_types: Array = []
	for stream_type \
			in [_stream_type_video, _stream_type_image, _stream_type_document]:
		if stream_type.is_pressed():
			stream_types.append(stream_type.get_text().to_lower())
	return stream_types


func _get_duration() -> String:
	var equality: String = \
			_duration_equality.get_item_text(_duration_equality.get_selected())
	return equality + str(int(_duration.get_value() * 60))


func _get_channel_ids() -> Array:
	var channel_ids: Array = []
	
	var tracker: Dictionary = _async_helper.connect_wrapped(
			get_tree(), "idle_frame", false)
	yield(_async_helper.wait_until_finished([tracker]), "completed")
	if _only_following.is_pressed():
		tracker = _async_helper.connect_wrapped(
				LBRYActions.get_followed_channels(), "completed")
		yield(_async_helper.wait_until_finished([tracker]), "completed")
		var followed_channels: Array = tracker["result"]
		for channel in followed_channels:
			channel_ids.append(channel.rsplit("#", true, 1)[1])
	return channel_ids


func _get_any_languages() -> Array:
	# TODO: what format are the languages meant to be given in? are only a
	# subset of languages valid?
	var languages: Array = []
	
	return languages


func _on_ClaimType_item_selected(_idx: int) -> void:
	# Stream type doesn't apply if "stream" or "repost" are not selected
	if not (_get_claim_type() in ["stream", "repost"]):
		_stream_type_video.set_disabled(true)
		_stream_type_image.set_disabled(true)
		_stream_type_document.set_disabled(true)
		_duration_equality.set_disabled(true)
		_duration.set_editable(false)
		_duration_text.set_self_modulate(Color(1, 1, 1, 0.3))
	else:
		if _stream_type_any.is_pressed() or _stream_type_video.is_pressed():
			_duration_equality.set_disabled(false)
			_duration.set_editable(true)
			_duration_text.set_self_modulate(Color(1, 1, 1, 1))
		_stream_type_video.set_disabled(false)
		_stream_type_image.set_disabled(false)
		_stream_type_document.set_disabled(false)


func _on_StreamType_toggled(_button_pressed: bool) -> void:
	var is_any_stream_type_pressed: bool = false
	var is_video_pressed: bool = false
	for stream_type \
			in [_stream_type_video, _stream_type_image, _stream_type_document]:
		if stream_type.is_pressed():
			is_any_stream_type_pressed = true
			if stream_type.get_text().to_lower() == "video":
				is_video_pressed = true
				break
	
	if is_any_stream_type_pressed:
		_stream_type_any.set_pressed(false)
	else:
		_stream_type_any.set_pressed(true)
	
	if is_video_pressed or not is_any_stream_type_pressed:
		_duration_equality.set_disabled(false)
		_duration.set_editable(true)
		_duration_text.set_self_modulate(Color(1, 1, 1, 1))
	else:
		_duration_equality.set_disabled(true)
		_duration.set_editable(false)
		_duration_text.set_self_modulate(Color(1, 1, 1, 0.3))


func _on_Duration_value_changed(value: float) -> void:
	_duration_text.set_text(str(value) + " mins")
