local function r()
    local files = file.Find("s/*.png", "DATA")
    if not files or #files == 0 then return "" end

    local randomFile = "s/" .. files[math.random(#files)]
    local f = file.Open(randomFile, "rb", "DATA")

    if not f then return "" end

    local data = f:Read(f:Size())
    f:Close()

    return data
end

local msg = ""

local Detours = {}

local old_tostring = tostring
local old_string_dump = string.dump

local old_Capture = render.Capture
local old_CapturePixels = render.CapturePixels

local old_debug_gethook = debug.gethook
local old_debug_sethook = debug.sethook
local old_debug_setfenv = debug.setfenv
local old_debug_getfenv = debug.getfenv
local old_debug_getupvalue = debug.getupvalue
local old_debug_getinfo = debug.getinfo
local old_debug_traceback = debug.traceback
local old_debug_getlocal = debug.getlocal

local old_fileDelete = file.Delete
local old_fileFind = file.Find
local old_fileExists = file.Exists

local old_require = require
local old_include = include

local old_HasFocus = system.HasFocus

local old_gcinfo = gcinfo
local old_collectgarbage = collectgarbage

local old_jit_funcinfo = jit.util.funcinfo
local old_jit_funcbc = jit.util.funcbc
local old_jit_attach = jit.attach

local _isnumber = isnumber
local _isfunction = isfunction

local memoryOffset = old_gcinfo()

--------------------------------------------------------------

_G.tostring = function(Object)
    return old_tostring(Detours[Object] or Object)
end
Detours[tostring] = old_tostring -- detour

_G.string.dump = function(func, ...)
    return old_string_dump(Detours[func] or func, ...)
end
Detours[string.dump] = old_string_dump -- detour

_G.debug.getinfo = function(func, ...)
    return old_debug_getinfo(Detours[func] or func, ...)
end
Detours[debug.getinfo] = old_debug_getinfo -- detour

_G.debug.gethook = function(thread)
    return old_debug_gethook(thread)
end
Detours[debug.gethook] = old_debug_gethook -- detour

_G.debug.sethook = function(thread, hook, mask, count)
    return old_debug_sethook(thread, hook, mask, count)
end
Detours[debug.sethook] = old_debug_sethook -- detour

_G.debug.setfenv = function(object, env)
    return old_debug_setfenv(object, env)
end
Detours[debug.setfenv] = old_debug_setfenv -- detour

_G.debug.getfenv = function(object)
    return old_debug_getfenv(Detours[object] or object)
end
Detours[debug.getfenv] = old_debug_getfenv -- detour

_G.debug.getupvalue = function(func, index)
    if not _isnumber(index) or not _isfunction(func) then
        return old_debug_getupvalue(func, index)
    end
    return old_debug_getupvalue(Detours[func] or func, index)
end
Detours[debug.getupvalue] = old_debug_getupvalue -- detour


local function FakeCapture()
    msg = "[ANTI SCREENGRAB] : Get Screengabbed"
    Autorun.log(msg)
    return r()
end

_G.render.Capture = FakeCapture
Detours[render.Capture] = old_Capture -- detour
_G.render.CapturePixels = FakeCapture
Detours[render.CapturePixels] = old_CapturePixels -- detour

local function BlockFileAccess(filename, mode)
    msg = "[ANTI FILE ACCESS] : blocked " .. mode .. " -> " .. (filename or "missing file")
    Autorun.log(msg)
    return false
end

_G.file.Write = function(filename, content) return BlockFileAccess(filename, "WRITE") end
_G.file.Append = function(filename, content) return BlockFileAccess(filename, "APPEND") end
_G.file.Delete = function(filename) return BlockFileAccess(filename, "DELETE") end
-- _G.file.Exists = function(filename) return BlockFileAccess(filename, "EXISTS") end
Detours[file.Delete] = old_fileDelete -- detour
-- Detours[file.Exists] = old_fileExists -- detour

_G.file.Find = function(filename, path, ...)
    if filename:find("data/s/") or filename:find("lua/") then
        msg = "[ANTI FILE ACCESS] : Blocked folder -> " .. filename
        Autorun.log(msg)
        return {} 
    end
    return old_fileFind(filename, path, ...)
end
Detours[file.Find] = old_fileFind -- detour

_G.system.HasFocus = function()
    return true
end
Detours[system.HasFocus] = old_HasFocus -- detour

_G.gcinfo = function()
    return math.max(0, old_gcinfo() - memoryOffset)
end
Detours[gcinfo] = old_gcinfo -- detour

_G.collectgarbage = function(what, arg)
    if what == "count" then
        return math.max(0, old_collectgarbage("count") - memoryOffset)
    else
        return old_collectgarbage(what, arg)
    end
end
Detours[collectgarbage] = old_collectgarbage -- detour

_G.jit.util.funcinfo = function(func, ...)
    return old_jit_funcinfo(Detours[func] or func, ...)
end
Detours[jit.util.funcinfo] = old_jit_funcinfo -- detour

_G.jit.util.funcbc = function(func, ...)
    return old_jit_funcbc(Detours[func] or func, ...)
end
Detours[jit.util.funcbc] = old_jit_funcbc -- detour

_G.jit.attach = function(callback, event)
    if not _isfunction(callback) then
        return old_jit_attach(callback, event)
    end
    return old_jit_attach(function(...)
        local args = {...}
        for i = 1, #args do
            args[i] = Detours[args[i]] or args[i]
        end
        return callback(unpack(args))
    end, event)
end
Detours[jit.attach] = old_jit_attach -- detour
Autorun.log("--------------------------- Detours loaded ! ---------------------------")
