extends Node

var udp := PacketPeerUDP.new()
var python_port := 5556


## INFO button_down in this context refers to my Stream Deck. I have buttons on it bound to broadcast UDP commands. Naming it button_down here is a bit weird though
signal on_button_down(message: String)

signal on_youtube_chat(user: String, msg: String, tex: Texture2D)

func _ready():
	if ConfigManager.get_setting("client_auth", "broadcaster_username") == ConfigManager.DEFAULT_SETTINGS.client_auth.broadcaster_username:
		return
	if udp.bind(5555, "127.0.0.1") != OK:
		push_error("Could not start UDP listener")

func _process(_dt):
	while udp.get_available_packet_count() > 0:
		var packet = udp.get_packet()

		var raw = packet.get_string_from_utf8()

		if raw.is_empty() and not packet.is_empty():
			# fallback to ASCII if UTF-8 doesn't get received. This will probably crash the overlay btw ¯\_(ツ)_/¯
			raw = packet.get_string_from_ascii()
		_parse_packet(raw)

func _parse_packet(content: String):
	var json = JSON.new()
	if json.parse(content) == OK and typeof(json.data) == TYPE_DICTIONARY:
		var data = json.data
		match data.get("type"):
			"ping":
				_send_pong()
			"youtube_chat":
				_fetch_pfp(data)
	else:
		on_button_down.emit(content)

## Communicate back to the YouTube Live python script so that it can actually begin looking for messages
func _send_pong():
	udp.set_dest_address("127.0.0.1", python_port)
	udp.put_packet(JSON.stringify({"type": "pong"}).to_utf8_buffer())

#region YouTube profile picture stuff (Twitch is handled via it's own TwitchBot system)
func _fetch_pfp(data: Dictionary):
	var http = HTTPRequest.new()
	add_child(http)
	http.request_completed.connect(_on_pfp_downloaded.bind(http, data))
	http.request(data["pfp"])


func _on_pfp_downloaded(_result, response_code, _headers, body, http_node, data):
	http_node.queue_free()
	if response_code == 200:
		var img = Image.new()
		# Universal Loader: peeks at magic bytes to choose format
		var err = _load_smart(img, body)
		if err == OK:
			var tex = ImageTexture.create_from_image(img)
			on_youtube_chat.emit(data["user"], data["message"], tex)

func _load_smart(img: Image, buffer: PackedByteArray) -> Error:
	if buffer.size() < 4:
		return ERR_INVALID_DATA

	# File signatures (YouTube profile images can be any one of these three formats):
	# WebP: (82, 73, 70, 70)
	if buffer[0] == 0x52 and buffer[1] == 0x49 and buffer[2] == 0x46 and buffer[3] == 0x46:
		return img.load_webp_from_buffer(buffer)

	# JPEG: (FF D8)
	if buffer[0] == 0xFF and buffer[1] == 0xD8:
		return img.load_jpg_from_buffer(buffer)

	# PNG: (89 50 4E 47)
	if buffer[0] == 0x89 and buffer[1] == 0x50 and buffer[2] == 0x4E and buffer[3] == 0x47:
		return img.load_png_from_buffer(buffer)

	return img.load_png_from_buffer(buffer)
#endregion
