local cg = FA_TOOLS.FA_Count
//print("Loading Fangli-Tool")
local FA = FA_TOOLS
local getlocals,setlocal, getinfo_callback, jitinfo_callback, tostring_callback, collectgarbage_callback, cg2

local function copy( tab, nTab, f )
    local _copy = {};
    for k, v in pairs( tab ) do 
        if ( !istable( v ) ) then 
            _copy[ k ] = v;
        else 
            nTab = nTab or {};
            nTab[ tab ] = _copy;
            if ( nTab[ v ] ) then 
                _copy[ k ] = nTab[ v ];
            else 
                _copy[ k ] = f( v, nTab, f );
            end
        end
    end
    return _copy;
end
local g = copy(_G, {}, copy)
local r = copy(debug.getregistry(), {}, copy)

local function setreturn(ret,lvl)
    for i=3,10,1 do
        local a,b = g.debug.getlocal(lvl or 4,i)
        if a == "HookTable" then
            g.debug.setlocal(lvl or 4,i,{["HookTable"] = function() return ret end})
        end
    end
end

local function createmove(cmd)

end

local function hudpaint()
    --draw.DrawText( "aaaaaaaaaaaaaa", "TargetID", 20, 20, Color(0,0,0,255), TEXT_ALIGN_LEFT ) 
end

local function think()

end

local function shoulddrawlocalplayer()
    setreturn(true)
end

local function calcview(ply, origin, angles, fov, znear, zfar)

end

function getlocals(lvl)
    if !lvl then return end
    lvl = lvl + 1
    local t = {}
    for i=1,20,1 do
        local a,b = g.debug.getlocal(lvl,i)
        if b then
            t[#t+1] = b
        end
    end
    return g.unpack(t)
end

function setlocal(name,val,lvl)
    local lvl = lvl or 2
    for i=1,20,1 do
        local a,b = g.debug.getlocal(lvl,i)
        if a == name then
            g.debug.setlocal(lvl,i,val) 
            return
        end
    end
    g.error("no local '"..name.."' found on level '"..g.tostring(lvl).."'")
end

local function get_varargs(offset, include_globals)

    local bindings = {}
    local level = offset + 1

    local varargs = {}
    do local i = -1; repeat
        local name, value = g.debug.getlocal(level, i)
        g.table.insert(varargs, value)
        i = i - 1
    until name == nil end
    bindings = varargs
    
    return bindings
end

local _func,_str,_count = nil,"",0

local function hook(event,line)
    if line == 71 then
        local a,b = g.debug.getlocal(2,2)
        if a == "gm" or a == "mv" then
            local lc = getlocals(2)
            local varargs = get_varargs(2)
            local tbl = {lc}

            if tbl[1] == "HUDPaint" then
                hudpaint()
            elseif tbl[1] == "Think" then
                think()
            elseif tbl[1] == "CalcView" then
                calcview(g.unpack(varargs))
            elseif tbl[1] == "ShouldDrawLocalPlayer" then
                shoulddrawlocalplayer()
            elseif tbl[1] == "CreateMove" then
                createmove(g.unpack(varargs))
            end
        end
    end
    if _func and g.type(_func) != "number" then
        _func(event,line)
    end
end


FA.FA_OldSetHook(hook, "l")

local _func,_str,_count = nil,"",0
FA.FA_SetCallback("DebugSet",function(func,str,count)
    if (!func or func == 0) and count == -1 and str == "turn_off_13337" then
        _func,_str,_count = nil,nil,nil
    end
    _func,_str,_count = func,str,count
end)

FA.FA_SetCallback("DebugGet",function()
    local tbl = {
        ["int"]     = _count,
        ["str"]     = _str,
        ["func"]    = _func,
    }
    return tbl
end)

function getinfo_callback(func,str)
    if type(func) == "number" then
        func = func + 2
    end

    local tbl = FA.FA_OldGetInfo(func)
    if !tbl or type(tbl) != "table" then
        return 0
    end

    if type(func) == "function" and #tbl > 0 then
        if func == debug.gethook then
            tbl.func = "function: builtin#133"
            tbl.ffid = 133
        elseif func == debug.sethook then
            tbl.func = "function: builtin#132"
            tbl.ffid = 132
        elseif func == debug.getinfo then
            tbl.func = "function: builtin#125"
            tbl.ffid = 125
        elseif func == tostring then
            tbl.func = "function: builtin#18"
            tbl.ffid = 18
        elseif func == jit.util.funcinfo then
            tbl.func = "function: builtin#141"
            tbl.ffid = 141
        end
    end

    if tbl.func == getinfo_callback or tbl.name == "FA_OldGetInfo" then
        return 0
    end

    if  ((tbl.linedefined and tbl.linedefined > -1) or
        (tbl.currentline and tbl.currentline > -1) or
        (tbl.lastlinedefined and tbl.lastlinedefined > -1) or
        (tbl.what and tbl.what == "Lua")) and
        (tbl.source and tbl.source == "@[C]")
    then
        tbl = 0
    end

    return tbl
end
FA.FA_SetCallback("DebugGetInfo",getinfo_callback)

function jitinfo_callback(func,str)
    local tbl = FA.FA_OldJitInfo(func,str)

    if func == debug.gethook then
        tbl.func = "function: builtin#133"
    elseif func == debug.sethook then
        tbl.func = "function: builtin#132"
    elseif func == debug.getinfo then
        tbl.func = "function: builtin#125"
    elseif func == tostring then
        tbl.func = "function: builtin#18"
    elseif func == jit.util.funcinfo then
        tbl.func = "function: builtin#141"
    end

    return tbl
end
FA.FA_SetCallback("JitFuncInfo",jitinfo_callback)

function tostring_callback(s)
    if !s then return {["str"] = "nil"} end
    local str = FA.FA_OldToString(s)

    if s == debug.gethook then
        str = "function: builtin#133"
    elseif s == debug.sethook then
        str = "function: builtin#132"
    elseif s == debug.getinfo then
        str = "function: builtin#125"
    elseif s == tostring then
        str = "function: builtin#18"
    elseif s == jit.util.funcinfo then
        str = "function: builtin#141"
    end

    return {["str"] = str}
end
FA.FA_SetCallback("ToString",tostring_callback)
FA.FA_Init()

local collected = false
function collectgarbage_callback(str,str2)
    local arg = str2
    if str2 == "" then arg = nil end

    if str == "count" then
        if collected then
            return FA.FA_OldGarbage("count")
        else
            print(FA.FA_OldGarbage("count")*0.982)
            return FA.FA_OldGarbage("count")*0.982
        end
    elseif str == "collect" then
        collected = true
        return FA.FA_OldGarbage(str)
    else
        return FA.FA_OldGarbage(str)
    end
end
FA.FA_SetCallback("CollectGarbage",collectgarbage_callback)

FA_TOOLS = nil  

cg2 = collectgarbage("count")
print(cg2)
print(cg)

//shit to fix:
//motherfucking collectgarbage(), really