---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by KraKss.
--- DateTime: 05/07/2023 16:17
---

local function KeyboardInput(TextEntry, ExampleText, MaxStringLenght)

    AddTextEntry('FMMC_KEY_TIP1', TextEntry)
    DisplayOnscreenKeyboard(1, "FMMC_KEY_TIP1", "", ExampleText, "", "", "", MaxStringLenght)
    blockinput = true

    while UpdateOnscreenKeyboard() ~= 1 and UpdateOnscreenKeyboard() ~= 2 do
        Citizen.Wait(0)
    end

    if UpdateOnscreenKeyboard() ~= 2 then
        local result = GetOnscreenKeyboardResult()
        Citizen.Wait(100)
        blockinput = false
        return result
    else
        Citizen.Wait(100)
        blockinput = false
        return nil
    end
end

---@class Radio
Radio = {}
Radio.__index = Radio

-- Constructor
function Radio:new()
    local object = setmetatable({}, Radio)
    object.displayed = false
    object.IsOn = false
    object.frequency = 0
    object.volume = 100
    object.micClicks = true
    object.displayEmptyFrequencies = true
    object.playersInFrequencies = {}
    return object
end

function Radio:translate(str)
    if (not Lang[cfg.lang][str]) then
        error(("The string '%s' does not exist in the language '%s'. Please add it."):format(str, cfg.lang))
    end
    return Lang[cfg.lang][str]
end

function Radio:setPlayersInFrequencies(tbl)
    self.playersInFrequencies = tbl
end

function Radio:enable(bool)
    PMA:setVoiceProperty("radioEnabled", bool)
end

function Radio:fetchPlayersInChannel()
    TriggerServerEvent("KraKss:radio:fetchPlayersInChannel")
end

function Radio:joinFrequency(frequency)
    if (frequency <= 0 or frequency > cfg.maxFrequency) then
        return
    end

    self.frequency = frequency
    PMA:setRadioChannel(frequency)
    self:fetchPlayersInChannel()
    ESX.ShowNotification(self:translate("joinedFrequency"):format(frequency))
end

function Radio:leaveFrequency()
    self.frequency = 0
    PMA:setRadioChannel(0)
    ESX.ShowNotification(self:translate("leftFrequency"))
    self:fetchPlayersInChannel()
end

function Radio:IsJobEqual(xPlayer, jobs)
    if (type(jobs) ~= "table") then
        return error("The parameter 'jobs' in the cfg must be a table.")
    end

    for _, job in ipairs(jobs) do
        if ((xPlayer.job.name == job) or (xPlayer.job2.name == job)) then
            return true
        end
    end
    return false
end

function Radio:IsJobFrequency(frequency)
    for _, jobFrequency in ipairs(cfg.privateJobFrequencies) do
        if (jobFrequency.frequency == frequency) then
            return true
        end
    end
    return false
end

function Radio:createMenu()
    self.mainMenu = RageUI.CreateMenu(cfg.menu.name, cfg.menu.subtitle)
    self.publicMenu = RageUI.CreateSubMenu(self.mainMenu, cfg.menu.name, cfg.menu.publicSubtitle)
    self.jobMenu = RageUI.CreateSubMenu(self.mainMenu, cfg.menu.name, cfg.menu.privateSubtitle)
    self.mainMenu:DisplayPageCounter(cfg.menu.displayPageCounter)
end

function Radio:drawMenu()
    local xPlayer = ESX.GetPlayerData()

    RageUI.IsVisible(self.mainMenu, function()
        self:drawMainMenu(xPlayer)
    end)

    RageUI.IsVisible(self.publicMenu, function()
        self:drawPublicMenu()
    end)

    RageUI.IsVisible(self.jobMenu, function()
        self:drawJobMenu(xPlayer)
    end)
end

function Radio:drawMainMenu(xPlayer)
    RageUI.Button(self:translate("enableRadio"), nil, { RightLabel = (self.IsOn) and self:translate("radioOn") or self:translate("radioOff") }, true, {
        onSelected = function()
            self.IsOn = not self.IsOn
            self:enable(self.IsOn)
        end
    })

    if (self.IsOn) then
        RageUI.Button(self:translate("enableMicClicks"), nil, { RightLabel = (self.micClicks) and self:translate("micClickOn") or self:translate("micClickOff") }, true, {
            onSelected = function()
                PMA:setVoiceProperty("micClicks", not self.micClicks)
                self.micClicks = not self.micClicks
            end
        })

        RageUI.SliderProgress((self:translate("volumeSlider")):format(self.volume), self.volume, 100, false, {
            ProgressBackgroundColor = { R = 0, G = 0, B = 0, A = 180 },
            ProgressColor = { R = 91, G = 179, B = 225, A = 255 },
        }, true, {
            onSliderChange = function(Index)
                self.volume = Index
                PMA:setRadioVolume(self.volume)
            end, onSelected = function()
                local vol <const> = KeyboardInput(self:translate("volumeTextEntry"), "", 9)
                if (tonumber(vol)) then
                    self.volume = ((tonumber(vol) <= 100) and (tonumber(vol) >= 0)) and tonumber(vol) or self.volume
                    PMA:setRadioVolume(self.volume)
                end
            end
        })

        RageUI.Line()

        RageUI.Button(self:translate("connectToFrequency"), nil,
                {
                    LeftBadge = (self.frequency == 0) and RageUI.BadgeStyle.Star,
                    RightLabel = (self.frequency ~= 0) and (self:translate("currentFrequency")):format(self.frequency) or ""
                }, true, {
                    onSelected = function()
                        local frequency <const> = KeyboardInput(self:translate("frequencyTextEntry"), "", 9)
                        if (self:IsJobFrequency(tonumber(frequency))) then
                            ESX.ShowNotification(self:translate("frequencyIsJobRestricted"))
                            return
                        end
                        self:joinFrequency(type(frequency) == "string" and tonumber(frequency) or 0)
                    end
                })

        RageUI.Button(self:translate("leaveCurrentFrequency"), nil, { RightLabel = "→" }, (self.frequency ~= 0), {
            onSelected = function()
                self:leaveFrequency()
            end
        })

        RageUI.Line()

        RageUI.Button(self:translate("publicFrequencies"), nil, { RightLabel = "→" }, true, {}, self.publicMenu)

        RageUI.Button(self:translate("jobFrequencies"), nil, { RightLabel = "→" }, xPlayer.job.name ~= "unemployed", {}, self.jobMenu)
    end
end

function Radio:drawPublicMenu()
    RageUI.Checkbox(self:translate("displayEmptyFrequencies"), nil, self.displayEmptyFrequencies, {}, {
        onChecked = function()
            self.displayEmptyFrequencies = true
        end,
        onUnChecked = function()
            self.displayEmptyFrequencies = false
        end
    })

    local function compareKeys(a, b)
        return tonumber(a) < tonumber(b)
    end

    local freq = {}
    for k in pairs(self.playersInFrequencies) do
        if (not self:IsJobFrequency(k)) then
            table.insert(freq, k)
        end
    end

    table.sort(freq, compareKeys)

    RageUI.Line()

    if (not freq[1]) then
        RageUI.Separator(self:translate("noPublicFrequencies"))
    end

    for _, k in ipairs(freq) do
        local v = self.playersInFrequencies[k]
        if (v == 0 and not self.displayEmptyFrequencies) then
            goto continue
        end

        RageUI.Button((self:translate("publicFrequencyNumber")):format(k), nil, { RightLabel = ("%s/%s"):format(v, cfg.publicFrequencyMaxPlayers) }, true, {
            onSelected = function()
                if (v < cfg.publicFrequencyMaxPlayers) then
                    self:joinFrequency(k)
                else
                    ESX.ShowNotification(self:translate("frequencyMaxedOut"):format(cfg.publicFrequencyMaxPlayers))
                end
            end
        })
        ::continue::
    end
end

function Radio:drawJobMenu(xPlayer)
    for _,v in pairs(cfg.privateJobFrequencies) do
        if (Radio:IsJobEqual(xPlayer, v.jobs)) then
            RageUI.Button(v.name, nil, { RightLabel = ("%s/%s"):format(self.playersInFrequencies[v.frequency] or 0, v.userLimit) }, true, {
                onSelected = function()
                    if (not self.playersInFrequencies[v.frequency] or self.playersInFrequencies[v.frequency] < v.userLimit) then
                        self:joinFrequency(v.frequency)
                    else
                        ESX.ShowNotification(self:translate("frequencyMaxedOut"):format(v.userLimit))
                    end
                end
            })
        end
    end
end

function Radio:openMenu()
    if (self.displayed) then
        return
    end

    if (not self.mainMenu) then
        self:createMenu()
        self:fetchPlayersInChannel()
    end

    RageUI.Visible(self.mainMenu, true)
    self.displayed = true

    CreateThread(function()
        while (self.displayed) do
            self:drawMenu()

            if (not RageUI.Visible(self.mainMenu) and
                not RageUI.Visible(self.publicMenu) and
                not RageUI.Visible(self.jobMenu)) then
                self.displayed = false
            end
            Wait(0)
        end
    end)
end

radio = Radio:new()
