-- job descriptor structure
local jobDescKeys = {
	CommandFile = "CommandFile",
	OutputFile = "OutputFile",
	InputFile = "InputFile",
	ErrorFile = "ErrorFile",
	Arguments = "Args",
	WorkingDirectory = "WorkingDirectory",
	JobName = "Name",
	JoinFiles = "JoinFiles",
	Environment = "Env",
	Email = "Email"
}

local DRMAA_ACTIONS = {
	SUSPEND = true,
	RESUME = true,
	HOLD = true,
	RELEASE = true,
	TERMINATE = true,
}

DRMAA_TIMEOUTOPTIONS = {
	WaitForever = 0,
	NoWait = 1,
}

local DRMAA_JOBOPTIONS = {
	AllJobs = 0,
	AnyJob = 1,
}

local getConstants = function ()
	DRMAA_TIMEOUTOPTIONS.WaitForever = lua_wrapper_get_drmaa_impl_WaitForever()
	DRMAA_TIMEOUTOPTIONS.NoWait = lua_wrapper_get_drmaa_impl_NoWait()
end

-- load loader
if not load_as_global then
	os.execute("echo $LD_LIBRARY_PATH")
	os.execute("echo $LUA_PATH")
	local genericLoaderOpen = assert(package.loadlib("genericloader.so", "luaopen_genericloader"))
	genericLoaderOpen()
	--require "genericloader"
end

-- load drmaa library
--local slurmLibOpen = assert(package.loadlib("/home/msv/ericaflr/sga-slurm/drmaaloader.so", "luaopen_drmaaloader"))
--local slurmLibOpen = assert(package.loadlib("/home/msv/ericaflr/sga-slurm/drmaa.so", "*"))
--slurmLibOpen()
--print("checking...", DRMAA_ACTIONS.TERMINATE)
ok, err = load_as_global("drmaa.so", "luaopen_drmaa")
if not ok then
	print("Error:", err)
end
getConstants()


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

checkJobDescriptor = function (jobDescriptor)
	if not jobDescriptor then
		return nil, "drmaa lua wrapper: jobDescriptor is required."
	elseif type(jobDescriptor)~= "table" then
		return nil, "drmaa lua wrapper: job descriptor must be a table."
	end

	do
		local commandFile = jobDescriptor[jobDescKeys.CommandFile]
		if not commandFile then
			return nil, "drmaa lua wrapper: job descriptor must contain a command."
		elseif type(commandFile)~="string" then
			return nil, "drmaa lua wrapper: job descriptor's command must be a string."
		end 
	end

	do
		local outputFile = jobDescriptor[jobDescKeys.OutputFile]
		if outputFile and type(outputFile)~="string" then
			return nil, "drmaa lua wrapper: job descriptor's output file must be a string."
		end
	end

	do
		local inputFile = jobDescriptor[jobDescKeys.InputFile]
		if inputFile and type(inputFile)~="string" then
			return nil, "drmaa lua wrapper: job descriptor's input file must be a string."
		end
	end

	do
		local errorFile = jobDescriptor[jobDescKeys.ErrorFile]
		if errorFile and type(errorFile)~="string" then
			return nil, "drmaa lua wrapper: job descriptor's error file must be a string."
		end
	end

	do
		local args = jobDescriptor[jobDescKeys.Arguments]
		if args and type(args)~="table" then
			return nil, "drmaa lua wrapper: job descriptor's arguments must be an array."
		end
		if args then
			for _, v in ipairs(args) do
				if type(v)=="table" then
					return nil, "drmaa lua wrapper: a joc can't receive a table as argument."
				end
			end
		end
	end

	do
		local workingDirectory = jobDescriptor[jobDescKeys.WorkingDirectory]
		if workingDirectory and type(workingDirectory)~="string" then
			return nil, "drmaa lua wrapper: job descriptor's working directory must be a string."
		end
	end

	do
		local name = jobDescriptor[jobDescKeys.Name]
		if name and type(name)~="string" then
			return nil, "drmaa lua wrapper: job descriptor's name must be a string."
		end
	end

	do
		local joinFiles = jobDescriptor[jobDescKeys.JoinFiles]
		if name~=nil and type(name)~="boolean" then
			return nil, "drmaa lua wrapper: job descriptor's join files must be a boolean."
		end
	end

	do
		local email = jobDescriptor[jobDescKeys.Email]
		if email and type(email)~="table" then
			return nil, "drmaa lua wrapper: job descriptor's email must be an array of strings."
		end
		
		if email then
			for _, v in ipairs(email) do
				if type(v)~="string" then
					return nil, "drmaa lua wrapper: job descriptor's denvironment must be an array of strings."
				end
			end
		end
	end

	do
		local env = jobDescriptor[jobDescKeys.Environment]
		if env and type(env)~="table" then
			return nil, "drmaa lua wrapper: job descriptor's denvironment must be an array of strings."
		end

		if env then
			for _, v in ipairs(env) do
				if type(v)~="string" then
					return nil, "drmaa lua wrapper: job descriptor's denvironment must be an array of strings."
				end
			end
		end
	end
	print ("Good job descriptor", jobDescKeys.CommandFile, DRMAA_ACTIONS.TERMINATE)
	return true
end

checkAction = function (action)
	if not action then
		return nil, "drmaa lua wrapper: action is required."
	elseif type(action)~="string" then
		return nil, "drmaa lua wrapper: action must be a string."
	end

	if DRMAA_ACTIONS[action] then
		return true
	end
	print("Action not found ", action)
	return false, "invalid action"
end

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

drmaa_init = function (contact)
	return lua_wrapper_drmaa_init(contact)
end

drmaa_exit = function ()
	return lua_wrapper_drmaa_exit()
end

drmaa_run_job = function (jobDescriptor)
	local ok, err = checkJobDescriptor(jobDescriptor)
	if not ok then
		--print "c err"
		return ok, err
	end
	return lua_wrapper_drmaa_run_job(jobDescriptor);
end

drmaa_job_ps = function (jobId)
	if not jobId then
		return nil, "drmaa lua wrapper: jobId is required."
	elseif type(jobId)~="string" then
		print(type(jobId))
		print()
		return nil, "drmaa lua wrapper: jobId must be a string."
	end
	return lua_wrapper_drmaa_job_ps(jobId)
end

drmaa_run_bulk_jobs = function (jobTemplate, bulk_start, bulk_end, bulk_incr)
	local ok, err = checkJobDescriptor(jobDescriptor)
	if not ok then
		return ok, err
	end
	--call
end

drmaa_control = function (jobId, action)
	if not jobId then
		return nil, "drmaa lua wrapper: jobId is required."
	elseif type(jobId)~="string" then
		return nil, "drmaa lua wrapper: jobId must be a string."
	end
	local ok, err = checkAction(action)
	if not ok then
		return ok, err
	end
	return lua_wrapper_drmaa_control(jobId, action)
end

drmaa_synchronize = function (jobIds, timeout)
	if not jobIds or (type(jobIds)~="string" and type(jobIds)~="table") then
		return nil, "drmaa lua wrapper: synchronize require an array job Ids or \"ALL\"."
	end

	if type(jobIds)~="table" then
		for _, v in ipairs(jobIds) do
			if type(v)~="string" then
				return nil, "drmaa lua wrapper: synchronize require a list of job Ids (strings) or \"ALL\"."
			end
		end
	end

	if (timeout) and type(timeout)~="number" and type(timeout)~="string" then
		return nil, "drmaa lua wrapper: timeout should be a number or \"NO WAIT\" or \"WAIT FOREVER\"."
	end

	local timeoutOption = nil
	if type(timeout)=="string" then
		if timeout == "NO WAIT" then
			timeoutOption = DRMAA_TIMEOUTOPTIONS.NoWait
		elseif timeout == "WAIT FOREVER" then
			timeoutOption = DRMAA_TIMEOUTOPTIONS.WaitForever
		else
			return nil, "drmaa lua wrapper: timeout should be a number or \"NO WAIT\" or \"WAIT FOREVER\"."
		end
	end
	--return lua_wrapper_drmaa_synchronize(args, timeoutOption or timeout)
end

drmaa_wait = function (jobId, timeout)
	if not jobId or (type(jobId)~="string" and jobId~=DRMAA_JOBOPTIONS.AnyJob) then
		return nil, "drmaa lua wrapper: wait require a job Id or ANY."
	end

	if (timeout) and type(timeout)~="number" and type(timeout)~="string" then
		return nil, "drmaa lua wrapper: timeout should be a number or NO WAIT or WAIT FOREVER."
	end

	local timeoutOption = nil
	if type(timeout)=="string" then
		if timeout == "NO WAIT" then
			timeoutOption = DRMAA_TIMEOUTOPTIONS.NoWait
		elseif timeout == "WAIT FOREVER" then
			timeoutOption = DRMAA_TIMEOUTOPTIONS.WaitForever
		else
			return nil, "drmaa lua wrapper: timeout should be a number or NO WAIT or WAIT FOREVER."
		end
	end

	local ret = {lua_wrapper_drmaa_wait2(jobId, timeout)}
        local exitStatus = table.remove(ret, 1)
        local exitCode = table.remove(ret, 1)
	
	return exitStatus, exitCode, ret
end

drmaa_get_contact = function ()
	return lua_wrapper_drmaa_get_contact()
end

drmaa_version = function ()
	return lua_wrapper_drmaa_version()
end

drmaa_get_DRM_system = function ()
	return lua_wrapper_drmaa_get_DRM_system()
end

drmaa_get_DRMAA_implementation = function ()
	return lua_wrapper_drmaa_get_DRMAA_implementation()
end
