--[[
	menu_plugins/lua_run_menu.lua
	Stoned
	===DStream===
]]

if (_G.Player) then return end
concommand.Add("lua_menu_reload",function() include("menu_plugins/lua_commands.lua") end)

if !RunString then require("luamenu") end
/*

local argstr

local function run( _, _, args )
	RunString( argstr or table.concat( args, " " ) )
	argstr = nil
end

local function complete( _, args )	
	argstr = args:Trim()
	
	if ( #argstr == 0 ) then return {} end
	
	local funcs = {}
	
	for name, value in pairs( _G ) do
		if ( name:Left( #argstr ) == argstr ) then
			if ( type( value ) == "function" ) then
				table.insert( funcs, "lua_run_autocomplete " .. name )
			elseif ( type( value ) == "table" ) then
				for name2 in pairs( value ) do
					table.insert( funcs, "lua_run_autocomplete " .. name .. "." .. name2 )
				end
			end
		end
	end
	
	table.sort( funcs )
	
	return funcs
end

concommand.Add( "lua_run_autocomplete", run, complete )

*/



debug = debug or {}

-- Thanks do Deco (Da Man) for this awesome function

function debug.getparams(f)
	local co = coroutine.create(f)
	local params = {}
	debug.sethook(co, function(event, line)
		local i, k, v = 1, debug.getlocal(co, 2, 1)
		while k do
			if k ~= "(*temporary)" then
				table.insert(params, k)
			end
			i = i+1
			k, v = debug.getlocal(co, 2, i)
		end
		error("~~end~~")
	end, "c")
	local res = {coroutine.resume(co)}
	if res[1] then
		error("The function provided defys the laws of the universe.", 2)
	elseif string.sub(tostring(res[2]), -7) ~= "~~end~~" then
		error("The function failed with the error: "..tostring(res[2]), 2)
	end
	return params
end

local function GetDir()
	for k, v in pairs(_R) do
		if string.Left(k,8) == "LOADLIB:" then
			return string.Trim(string.gsub(string.sub(k,10,string.find(k,"\\lua")),"/","\\"))
		end
	end
	return false
end

local function FindInEnvironment(env,str)
	local tbl = {}
	--if str == "" then return tbl end
	local len = string.len(str)
	for k, v in pairs(env) do
		if string.Left(k,len) == str then
			local str = k
			if type(v) == "function" then
				str = str.."("
			end
			table.insert(tbl,str)
		end
	end
	return tbl
end

local MIN_CHAR_AUTOCOMPLETE = 3
local SEP = {"=","%("}

--TODO: ALLOW RECURSIVE TABLE LISTING, so you can do package.s and it'll list package.seeall and allow it to keep going down in dimensions
local function ParseRunToAutoComplete(str)
	if string.len(str) > 1 and string.Right(str,1) != "(" then
		local fstr = string.TrimLeft(str)
		for k, v in pairs(SEP) do
			fstr = string.gsub(fstr,v," ")
		end
		local tbl = string.Explode(" ",fstr)
		local lastStr = string.Trim(table.remove(tbl))
		local match
		if lastStr == "" then
			return {}
		elseif lastStr != "." and string.find(string.reverse(lastStr),"%.") != nil then
			local tblS
			local lastn = 1
			while true do
				local n = string.find(lastStr,"%.",lastn)
				if n == nil then break end
				if tblS then
					tblS = tblS[string.sub(lastStr,lastn,n-1)]
					if not tblS then
						tblS = {}
						lastn = string.len(lastStr)
						break
					end
				else
					tblS = _G[string.sub(lastStr,lastn,n-1)]
				end
				lastn = n+1
			end
			match = FindInEnvironment(tblS or {},string.sub(lastStr,lastn))
			local lastStr = string.sub(lastStr,1,string.len(lastStr) - (string.find(string.reverse(lastStr),"%.")-1))
			for k, v in pairs(match) do
				match[k] = lastStr..v
			end
		else
			match = FindInEnvironment(_G,lastStr)
		end
		if table.getn(match) != 0 then
			local firstStr = string.sub(str,1,string.len(table.concat(tbl," "))+1) --just added trimleft thingy, test to do
			for k, v in pairs(match) do
				match[k] = "lua_run_con"..firstStr..v
			end
			table.insert(match,"")
			return match
		end
	end
	return {}
end
--[[
local rawiowrite = rawio.writefile
local function Nothing() return 0 end
rawio.readfile = Nothing
rawio.writefile = Nothing
rawio.deletefile = Nothing
rawio.mkdir = Nothing
]]
local LastArgs = ""
concommand.Add("lua_run_menu",function (objPl,strCmd,tblArgs)
	local str = ""
	if string.len(LastArgs) > 1 then
		str = string.sub(LastArgs,2) --Get rid of the space at the beginning
	else
		str = table.concat(tblArgs," ")
	end
	RunString(str)
	--rawiowrite(dir.."lua\\_temp_basic.lua",str)
	--include('_temp_basic.lua')
	--[[
	else
		ErrorNoHalt("Cannot find any directory to write temp lua file to!\n")
	end
	]]
end,function (strCmd,strArgs)
	LastArgs = strArgs
	--maybe add an autocomplete function call thingy? in suggestions?
	return ParseRunToAutoComplete(strArgs)
end)

local function ParseOpenscriptToAutoComplete(strCmd,strArgs) --Using aVoN's code, thank you aVoN
	local s = (strArgs or ""):Trim()
	if s == "" then return end
	local path = ""
	if s:find("/") then  
		path = s:gsub("/[^/]+$","").."/"  
	end  
	local files = {}
	for _,v in pairs(file.FindInLua(s.."*")) do  
		if not (v == "." or v == "..") and (v:find("%.lua") or not v:find("%.")) then  
			local file = (path..v):gsub("[/\\]+","/")
			table.insert(files,strCmd.." "..file)
		end  
	end
	-- Called from the MENU lua instance. The table with n strings returned does only use n-1 in autocomplete. So push one more empty string  
	table.insert(files,"")
	return files
--[[ --My old code
	if string.len(strArgs) > 1 then
		local tblFolders = string.Explode("/",string.Right(strArgs,-2))
		local lastStr = table.remove(tblFolders)
		local theDir = table.concat(tblFolders,"/")
		if #tblFolders > 0 then theDir = theDir.."/" end
		local tbl = table.Add(file.FindDir("../lua/"..theDir..lastStr.."*."),file.Find("../lua/"..theDir..lastStr.."*.lua"))
		for k, v in pairs(tbl) do
			tbl[k] = "lua_openscript_con "..theDir..v
		end
		--PrintTable(tbl)
		table.insert(tbl,"")
		return tbl
	end
	return {}
	]]
end

concommand.Add("lua_openscript_menu",function (objPl,strCmd,tblArgs)
	include(table.concat(tblArgs," "))
end,function (strCmd,strArgs)
	return ParseOpenscriptToAutoComplete(strCmd,strArgs)
end)

local function FindInTable( tab, find, parents, depth )

	depth = depth or 0
	parents = parents or ""
	
	if ( depth > 3 ) then return end
	depth = depth + 1
	
	for k, v in pairs ( tab ) do
	
		if ( type(k) == "string" ) then
		
			if ( k && k:lower():find( find:lower() ) ) then

				print("\t", parents, k, " - (", type(v), " - ", v, ")")
			
			end
			
			// Recurse
			if ( type(v) == "table" &&
				k != "_R" &&
				k != "_E" &&
				k != "_G" &&
				k != "_M" &&
				k != "_LOADED" &&
				k != "__index" ) then
				
				local NewParents = parents .. k .. ".";
				FindInTable( v, find, NewParents, depth )
			
			end
		
		end
	
	end

end



local function Find( ply, command, arguments )
	if ( ply && !ply:IsAdmin() ) then return end
	if ( !arguments[1] ) then return end
	print("Finding '", arguments[1], "' CLIENTSIDE:\n")
	FindInTable( _G, arguments[1] )
	FindInTable( _R, arguments[1] )
	print("\n")
end

concommand.Add("lua_find_menu",Find)
