extends Node

var net = NetworkedMultiplayerENet.new()
var api = MultiplayerAPI.new()
var port = 8081
var maxplayer = 4
export(NodePath) var database

func _ready():
	print('listening to port: ' + str(port))
	net.create_server(port, maxplayer)
	
	self.set_custom_multiplayer(api)
	custom_multiplayer.set_root_node(self)
	custom_multiplayer.set_network_peer(net)
	
	net.connect("peer_disconnected",self,"disc")
	net.connect("peer_connected",self,"conn")
	get_parent().get_node('Levelselect').loadlevel('test', true)
	pass # Replace with function body.

func _process(_delta):
	custom_multiplayer.poll()

var playerphsyics = preload('res://playerphysics.tscn')

func conn(id):
	print('client connected, id: ' + str(id))
	yield(get_tree(),"physics_frame")
	rpc_id(0,'ping')
	rpc_id(0,'tokerequest')

export var db_validation = true

remote func tokenreply(token, username):
	var db = get_parent().get_node('PostgreSQL')
	var data = db.Read('validtokens_database','username',"'"+str(username)+"'")
	var message = 'token validated'
	if db_validation:
		if data == [] or data == null:
			message = "no token found"
			return
		if data[0][2] != token:
			message = "token is invalid"
		print('check tokens....')
	print(token)
	print(data)
	print(message)
	if username == null or username == "":
		username = 'player ' +  str(api.get_rpc_sender_id()) + ' '
	if message == 'token validated':
		if game_status == 'await':
			player_spawn_queue[api.get_rpc_sender_id()] = {'id' : str(api.get_rpc_sender_id()), 'username':username, 'can_spawn':true}
			user_state_dict[str(username)] =  ' ...await'
			usernames_dict[api.get_rpc_sender_id()] =  str(username)
			rpc_id(0,'on_player_state_data',user_state_dict)
		rpc_id(api.get_rpc_sender_id(),'on_queue_spawn')
		rpc_id(api.get_rpc_sender_id(),'on_token_confirmed')

remote func spawn_request():
	if player_spawn_queue.has(api.get_rpc_sender_id()):
		if player_spawn_queue[api.get_rpc_sender_id()].can_spawn:
			user_state_dict[usernames_dict[api.get_rpc_sender_id()]] =  ' ready'
			rpc_id(0,'on_player_state_data',user_state_dict)
			if not user_state_dict.values().has(' ...await'):
				for x in player_spawn_queue.keys():
					player_spawn(player_spawn_queue[x],x)
					rpc_id(x,'on_spawn_request_reply')
					player_spawn_queue.erase(x)
				game_status = 'game_started'

func player_spawn(arg, arg2):
	var id = arg.id
	var username = arg.username
	print('clients connected: ' + str(custom_multiplayer.get_network_connected_peers().size()))
	var instance = playerphsyics.instance()
	instance.name = id
	$players.add_child(instance)
	send_list_of_usernames(arg2, username)
	rpc_id(arg2,'loadlevel','test')

var player_spawn_queue = {}

func send_list_of_usernames(user, username):
	rpc_id(user,'_on_usernames', usernames_dict)
	rpc_id(0,'_on_usernames', { user : username } )

var messages_array = []
var messages_array_2 = []
var usernames_dict = {}
var user_state_dict = {}
var game_status = 'await'

remote func chat_messages(message):
	if $players.has_node(str(api.get_rpc_sender_id())):
		var buff = usernames_dict[api.get_rpc_sender_id()] + ': ' + str(message)
		messages_array.append( buff )
		rpc_id(0,'_On_chat_Message', str(message), api.get_rpc_sender_id())

remote func connected_peer():
	print('syncing clients')
	rpc_id(0,'_On_Peer_Connected')

func makedummmy():
	var node = api.get_rpc_sender_id()
	$players.get_node(str(node)).add_to_group('dummy')

remote func send_clients():
	rpc_id(api.get_rpc_sender_id(), 'client_data', custom_multiplayer.get_network_connected_peers())
# extra

func disc(arg):
	print('client disconnected, id: ' + str(arg))
	rpc_id(0,'_On_Player_Disconnect',arg)

remote func latency(arg):
	rpc_id(api.get_rpc_sender_id(), 'returnping', arg)

remote func input_handler(arg,arg2):
	var id = api.get_rpc_sender_id()
	if $players.has_node(str(id)):
		$players.get_node(str(id)).input = arg
		$players.get_node(str(id)).input2 = arg2

var tick = 0
export var tickrate = 3

func _physics_process(delta):
	var position_datachunk = {}
	for i in $players.get_children():
		position_datachunk[i.name] = i.global_position
	rpc_unreliable_id(0, 'player_position', position_datachunk)
	
	var animation_datachunk = {}
	for i in $players.get_children():
		animation_datachunk[i.name] = i.animation
	rpc_unreliable_id(0, 'player_animation', animation_datachunk)
	
	synnc($projectiles.get_children(), 'projectiles_sync')
	
	tick += 1
	if fmod(tick,tickrate) == 0:
		synnc(get_tree().get_nodes_in_group('enemy'), 'enemies_position_2')
#		var enemies_datachunk = PoolByteArray()
#		for i in $enemies.dict.arraypos.size():
#			if $enemies.dict.arrayvida[i] > 0:
#				var pos = $enemies.dict.arraypos[i]
#				enemies_datachunk.append_array( return_int16(pos.x) )
#				enemies_datachunk.append_array( return_int16(pos.y) )
#				var bytetest : PoolByteArray
#				bytetest.append($enemies.dict.type[i] )
#				enemies_datachunk.append_array( bytetest )
#		rpc_unreliable_id(0, 'enemies_position_2', enemies_datachunk)

func _enemy_dmg(enemy_id):
	rpc_unreliable_id(0, 'enemy_dmg_anim', enemy_id)

func pshootanim(arg):
	rpc_unreliable_id(0, 'aimanim', arg)

func synnc(arg,arg1):
	var projectile_datachunk = PoolByteArray()
	for i in arg:
		var pos = i.global_position
		projectile_datachunk.append_array( return_int16(pos.x) )
		projectile_datachunk.append_array( return_int16(pos.y) )
		var bytetest : PoolByteArray
		bytetest.append(i.type)
		bytetest.append(i.fliph)
		projectile_datachunk.append_array( bytetest )
	rpc_unreliable_id(0, arg1, projectile_datachunk)

func return_int16(number):
	var int16 = number + 32768
	var bytetest : PoolByteArray
	var byte1:int = int(int16/255)
	var byte2:int = int(fmod(int16,255))
	bytetest.append(byte1)
	bytetest.append(byte2)
	return bytetest

func player_anim(attack,arg):
	rpc_id( 0,'attack_anim', attack, int(arg) )

func hp_update(vida, id):
	rpc_id( 0,'atr_update', {id:{'hp':vida}})

func kill_update(kill, xp, lv, nxt, id):
	rpc_id( 0,'atr_update', {id:{'k':kill, 'xp':xp, 'lv':lv, 'nxt':nxt}})

func level_up(lv, maxhp, gain, dmgup, id):
	rpc_id( 0,'level_up', lv, id)
	$players.get_node(str(id)).regenhp(gain)
	$players.get_node(str(id)).dmg += dmgup
	rpc_id( 0,'atr_update', {id:{'maxhp':maxhp}})
	
#	gen_power_queue(str(id))

#powerup code

var queue_powermenu_request = {
#	'id' : {'power':['a','b','c'],'client':0}
}

func gen_power_queue(client):
	var time = str(OS.get_system_time_msecs())+str(client)
	queue_powermenu_request[time] = {}
	queue_powermenu_request[time]['power'] = gen_power()
	queue_powermenu_request[time]['client'] = client
	rpc_id( int(client), 'powerpick', queue_powermenu_request[time]['power'] , time )
	_pauser_gen(false)

remote func optionpick(id, choice):
	var client = api.get_rpc_sender_id()
	if queue_powermenu_request.has(id):
		var power = queue_powermenu_request[id]['power'][choice]
		print(power)
		if $players.has_node(str(client)):
			$players.get_node(str(client)).add_power(power)
		queue_powermenu_request.erase(id)
	print(queue_powermenu_request)
	_pauser_gen(true)

func _pauser_gen(arg):
	set_physics_process(arg)
	$enemies.set_physics_process(arg)
	for i in $players.get_children():
		i.set_physics_process(arg)

func gen_power():
	return ['a','b','c']

