local PLUGIN = PLUGIN
util.AddNetworkString("ixRadioSetFrequency")
util.AddNetworkString("ixRadioToggleListen")
util.AddNetworkString("ixRadioToggleTransmit")

function PLUGIN:SyncRadioState(client, frequency, listen, transmit)
	local character = client:GetCharacter()

	if (!character) then
		return
	end

	frequency = math.Round(math.Clamp(frequency or self.defaultFrequency, self.minFrequency, self.maxFrequency), self.frequencyPrecision)
	listen = listen and true or false
	transmit = transmit and true or false

	if (!listen) then
		transmit = false
	end

	character:SetData("radioFrequency", frequency)
	character:SetData("radioListen", listen)
	character:SetData("radioTransmit", transmit)

	client:SetNetVar("radioFrequency", frequency)
	client:SetNetVar("radioListen", listen)
	client:SetNetVar("radioTransmit", transmit)
end

function PLUGIN:PlayerLoadedCharacter(client, character, lastChar)
	local frequency = character:GetData("radioFrequency", self.defaultFrequency)
	
	-- Force radio to be OFF after reconnect or character load
	local listen = false
	local transmit = false

	self:SyncRadioState(client, frequency, listen, transmit)
end

net.Receive("ixRadioSetFrequency", function(_, client)
	local character = client:GetCharacter()
	if client:IsAdminMode() then return end

	if (!character) then
		return
	end

	local frequency = net.ReadFloat()

	if (!isnumber(frequency)) then
		return
	end

	frequency = math.Round(math.Clamp(frequency, PLUGIN.minFrequency, PLUGIN.maxFrequency), PLUGIN.frequencyPrecision)

	local listen = character:GetData("radioListen", true)
	local transmit = character:GetData("radioTransmit", true)

	if (!listen) then
		transmit = false
	end

	PLUGIN:SyncRadioState(client, frequency, listen, transmit)

	local format = "%0." .. PLUGIN.frequencyPrecision .. "f"
	client:Notify("Частота рации установлена на " .. string.format(format, frequency))
end)

net.Receive("ixRadioToggleListen", function(_, client)
	local character = client:GetCharacter()
	if client:IsAdminMode() then return end

	if (!character) then
		return
	end

	local listen = !character:GetData("radioListen", true)
	local frequency = character:GetData("radioFrequency", PLUGIN.defaultFrequency)
	local transmit = character:GetData("radioTransmit", true)

	if (!listen) then
		transmit = false
	end

	PLUGIN:SyncRadioState(client, frequency, listen, transmit)
	client:Notify(listen and "Звук рации включен" or "Звук рации выключен")

	if (!listen and transmit) then
		client:Notify("Передача микрофона выключена")
	end
end)

net.Receive("ixRadioToggleTransmit", function(_, client)
	local character = client:GetCharacter()
	if client:IsAdminMode() then return end

	if (!character) then
		return
	end

	local listen = character:GetData("radioListen", true)
	local frequency = character:GetData("radioFrequency", PLUGIN.defaultFrequency)

	if (!listen) then
		PLUGIN:SyncRadioState(client, frequency, listen, false)
		client:Notify("Сначала включите звук рации")
		return
	end

	local transmit = !character:GetData("radioTransmit", true)

	PLUGIN:SyncRadioState(client, frequency, listen, transmit)
	client:Notify(transmit and "Передача микрофона включена" or "Передача микрофона выключена")
end)

function PLUGIN:PlayerCanHearPlayersVoice(listener, speaker)
	if (listener == speaker) then
		return
	end
	if listener:IsAdminMode() then return end
	if speaker:IsAdminMode() then return end

	local listenerChar = listener:GetCharacter()
	local speakerChar = speaker:GetCharacter()

	if (!listenerChar or !speakerChar) then
		return
	end


	if (!self:IsListening(listener)) then
		return
	end

	if (!self:IsListening(speaker)) then
		return
	end

	if (!self:IsTransmitting(speaker)) then
		return
	end

	local lf = self:GetFrequency(listener)
	local sf = self:GetFrequency(speaker)

	if (math.abs(lf - sf) > self.frequencyTolerance) then
		return
	end

	return true, false
end
