-- Discord Colors List (Source: https://gist.github.com/thomasbnt/b6f455e2c7d743b796917fa3c205f812)
local colors = {
    ['default'] = 0,
    ['aqua'] = 1752220,
    ['darkaqua'] = 1146986,
    ['green'] = 5763719,
    ['darkgreen'] = 2067276,
    ['blue'] = 3447003,
    ['darkblue'] = 2123412,
    ['purple'] = 10181046,
    ['darkpurple'] = 7419530,
    ['luminousvividpink'] = 15277667,
    ['darkvividpink'] = 11342935,
    ['gold'] = 15844367,
    ['darkgold'] = 12745742,
    ['orange'] = 15105570,
    ['darkorange'] = 11027200,
    ['red'] = 15548997,
    ['darkred'] = 10038562,
    ['grey'] = 9807270,
    ['darkgrey'] = 9936031,
    ['darkergrey'] = 8359053,
    ['lightgrey'] = 12370112,
    ['navy'] = 3426654,
    ['darknavy'] = 2899536,
    ['yellow'] = 16776960
}

-- Debug Print
local function DebugPrint(text)
    print("[^5Discord Logs^0] (^1ERROR^0) " .. text .. "^0")
end

-- Source: https://stackoverflow.com/a/27028488
local function DumpTable(o)
   if type(o) == 'table' then
      local s = '{ '
      for k,v in pairs(o) do
         if type(k) ~= 'number' then k = '"'..k..'"' end
         s = s .. '['..k..'] = ' .. DumpTable(v) .. ','
      end
      return s .. '} '
   else
      return tostring(o)
   end
end

function GetWeaponLabel(weaponHash)
    for k,v in pairs(Config.WeaponLabels) do
        if GetHashKey(k) == weaponHash then
            return v
        end
    end

    return weaponHash
end

-- @param resource string (auto-filled)
-- @param data table
    -- @param category string (required)
    -- @param title string (required)
    -- @param action string
    -- @param color string
    -- @param players table <id, role>
    -- @param info table <name, value>
    -- @param takeScreenshot boolean
    -- @param screenshotTargetId int
local function CreateLog(resource, data)
    if not data then return end
    
    local log_type = "general"
    local text = ""
    local fields = {}

    -- Define log type (singleplayer | multiplayer | general)
    if data.players then
        if type(data.players) == "table" then
            if #data.players == 1 then
                log_type = "singleplayer"
            else
                log_type = "multiplayer"
            end

            -- Add players' info to discord embed fields
            for k,v in pairs(data.players) do
                table.insert(fields, {
                    name = 'ㅤ',
                    value = 'ㅤ',
                    inline = false,
                })
    
                table.insert(fields, {
                    name = ""..v.role.." Name & ID",
                    value = ""..GetPlayerName(v.id).." ["..v.id.."]",
                    inline = true,
                })
    
                table.insert(fields, {
                    name = ""..v.role.." Identifier",
                    value = ""..GetPlayerIdentifierByType(v.id, Config.MainIdentifier).."",
                    inline = true,
                })
            end
        end
    end

    -- Category is missing, print error
    if not data.category then
        DebugPrint("Category is missing. Resource: " .. resource or GetCurrentResourceName())
        return
    end

    -- Category has no webhook defined, print error
    if not Config["Webhooks"][data.category] then
        DebugPrint("Category webhook doesn't exist. Category: " .. data.category)
        return
    end

    -- Title is missing, print error
    if not data.title then
        DebugPrint("Title is missing. Category: " .. data.category)
        return
    end

    -- Add extra information to the log
    if data.info then
        if type(data.info) == "table" then
            for i = 1, #data.info do
                if data.info[i].value then
                    if type(data.info[i].value) == "table" then
                        text = text .. "\n__" .. data.info[i].name .. ":__ " .. DumpTable(data.info[i].value) .. ""
                    else
                        text = text .. "\n__" .. data.info[i].name .. ":__ " .. data.info[i].value .. ""
                    end
                end
            end
        end
    end

    -- Add invoking resource to the log
    if resource then
        text = text .. "\nLog generated by: **"..resource.."**"
    end

    -- Discord Embed
    local embed = {
        ["color"] = colors[string.lower(data.color)] or colors['default'],
        ["title"] = data.action and ""..data.title.." ("..data.action..")" or data.title,
        ["description"] =  text,
        ["thumbnail"] = {
            ["url"] = Config.ServerLogo
        },
        ["fields"] = fields,
        ["footer"] = {
                ["text"] = ""..Config.ServerName.." - "..os.date("%c").." (Server Time)",
                ["icon_url"] = Config.ServerLogo
        },
    }

    -- Take screenshot of player's screen if requested
    if GetResourceState("screenshot-basic") == "started" and data.takeScreenshot then
        if (not log_type == "singleplayer" and not log_type == "multiplayer") then return end

        local target = data.screenshotTargetId or data.players[1].id
        local screenshot = lib.callback.await("DiscordLogs:Client:CB:GetScreenshot", target, Config.Webhooks["screenshots"]) 

        if screenshot then
            embed["image"] = {
                ["url"] = screenshot
            }
        else
            DebugPrint("Failed to take a screenshot of ".. GetPlayerName(target) .." [".. target .."]")
        end
    end

    -- Post log to Discord
    PerformHttpRequest(Config.Webhooks[data.category], function(err, text, headers) end, 'POST', json.encode({["username"] = Config.ServerName, ["avatar_url"] = Config.ServerLogo, embeds = {embed}}),  { ['Content-Type'] = 'application/json' })
end

exports("CreateLog", function(data)
    CreateLog(GetInvokingResource() ~= GetCurrentResourceName() and GetInvokingResource() or nil, data)
end)