extends Node

export var autojoin = true
export var lobby = "" # Will create a new lobby if empty.

var client: WebSocketClient = WebSocketClient.new()
var code = 1000
var reason = "Unknown"

signal lobby_joined(lobby)
signal connected(id)
signal disconnected()
signal peer_connected(id)
signal peer_disconnected(id)
signal offer_received(id, offer)
signal answer_received(id, answer)
signal candidate_received(id, mid, index, sdp)
signal lobby_sealed()

func _init():
	client.connect("data_received", self, "_parse_msg")
	client.connect("connection_established", self, "_connected")
	client.connect("connection_closed", self, "_closed")
	client.connect("connection_error", self, "_closed")
	client.connect("server_close_request", self, "_close_request")


func connect_to_url(url):
	close()
	code = 1000
	reason = "Unknown"
	client.connect_to_url(url)


func close():
	client.disconnect_from_host()


func _closed(was_clean = false):
	emit_signal("disconnected")


func _close_request(code, reason):
	self.code = code
	self.reason = reason


func _connected(protocol = ""):
	#client.get_peer(1).set_write_mode(WebSocketPeer.WRITE_MODE_TEXT)
	if autojoin:
		join_lobby(lobby)


func _parse_msg():
	#var pkt_str: String = client.get_peer(1).get_packet().get_string_from_utf8()
	var data=client.get_peer(1).get_packet().get_string_from_utf8()
	var msg = parse_json(data)
	print("new message: ", data)
	#var req: PoolStringArray = pkt_str.split("\n", true, 1)
	#if req.size() != 2: # Invalid request size
	#	return

	#var type: String = req[0]
	#if type.length() < 3: # Invalid type size
	#	return
	var type = msg["mtype"]

	if type == "J":
		emit_signal("lobby_joined", msg["payload"])
		return
	elif type == "S":
		emit_signal("lobby_sealed")
		return

	if type == "I":
		emit_signal("connected", msg["id"])
	elif type == "N":
		# Client connected
		emit_signal("peer_connected", msg["payload"])
	elif type == "D":
		# Client connected
		emit_signal("peer_disconnected", msg["id"])
	elif type == "O":
		# Offer received
		emit_signal("offer_received", msg["id"], msg["payload"])
	elif type == "A":
		# Answer received
		emit_signal("answer_received", msg["id"], msg["payload"])
	elif type == "C":
		# Candidate received
		var canddata = msg["payload"]
		print("incoming candidate: ", canddata)
		emit_signal("candidate_received", msg["id"], canddata["mid"], canddata["index"], canddata["sdp"])


func join_lobby(lobby):
	#return client.get_peer(1).put_packet(("J: %s\n" % lobby).to_utf8())
	_send_msg("J", "", lobby)


func seal_lobby():
	#return client.get_peer(1).put_packet("S: \n".to_utf8())
	return _send_msg("S", "", "")

func send_candidate(id, mid, index, sdp) -> int:
	var data = {"mid": mid, "index": index, "sdp": sdp}
	print("sending candidate: ", id, data)
	return _send_msg("C", id, data)


func send_offer(id, offer) -> int:
	print("sending offer: ", id, offer)
	return _send_msg("O", id, offer)


func send_answer(id, answer) -> int:
	return _send_msg("A", id, answer)


func _send_msg(type, id, data) -> int:
	#return client.get_peer(1).put_packet(("%s: %d\n%s" % [type, id, data]).to_utf8())
	var msg
	if id:
		msg = {"id": id, "mtype": type, "payload": data}
	else:
		msg = {"mtype": type, "payload": data}
	return client.get_peer(1).put_packet(to_json(msg).to_utf8())


func _process(delta):
	var status: int = client.get_connection_status()
	if status == WebSocketClient.CONNECTION_CONNECTING or status == WebSocketClient.CONNECTION_CONNECTED:
		client.poll()
