local fileSystem = require "rasa.filesystem"

module(..., package.seeall)

--[[
	https://rasa.com/docs/rasa/command-line-interface
	sample:
		rasa train --config /root/my_rasa/vccs/vcc2/test_rasa_app14/config.yml --out /root/my_rasa/vccs/vcc2/test_rasa_app14/models/ --domain /root/my_rasa/vccs/vcc2/test_rasa_app14/ --data /root/my_rasa/vccs/vcc2/test_rasa_app14/data/-
]]--
function Train (info)
	assert(type(info) == "table")
	--LogDebug("[RASA_COMMANDLINE:Train] Traing Info -> %s.", json.encode(info))
	assert(info.appId)
	assert(info.vcc)

	local directories = fileSystem.GetVccAppDirectories(info.vcc, info.appId)
	local commandLine = ("rasa train --config %s --out %s --domain %s --data %s --force"):format(
		directories.fullConfigYMLName,
		directories.modelDir,
		directories.domainDir,
		directories.dataDir
	)

	LogDebug("[RASA_COMMANDLINE:Train] Training App: '%s', Vcc: '%s' command: %s.", info.appId, info.vcc, commandLine)
	local success, code = pcall(os.execute, commandLine)
	--LogDebug("[RASA_COMMANDLINE:Train] command line result. success: %s, code: %s.", success, code)
	if not success or code ~= 0 then
		LogError("[RASA_COMMANDLINE:Train] Error Train App: '%s', Vcc: '%s'. RASA Command line. Error code: '%s'", info.appId, info.vcc, code)
		return false, {result = "UNABLE TO TRAIN RASA APP - RASA COMMAND LINE ERROR", code = code} --, info = info}
	end

	LogDebug("[RASA_COMMANDLINE:Train] Success Training App: '%s', Vcc: '%s'.", info.vcc, info.appId)
	local response = {}
	return true, response
end

--[[
	https://rasa.com/docs/rasa/command-line-interface
	sample:
		nohup /usr/local/bin/rasa run --model /root/my_rasa/vccs/vcc1/rasaapp1/models --log-file /root/my_rasa/vccs/vcc1/rasaapp1/RUN.log --enable-api -p 5006 -v -vv < /dev/null > /dev/null 2>&1 &
]]--
function RunRasaApp (info)
	assert(type(info) == "table")
	--LogDebug("[RASA_COMMANDLINE:RunRasaApp] Running Rasa App Info -> %s.", json.encode(info))
	assert(info.appId)
	assert(info.vcc)
	assert(info.app)
	assert(info.app.runtime)
	assert(info.app.runtime.port)

	LogDebug("[RASA_COMMANDLINE:RunRasaApp] Running Rasa App '%s', vcc '%s', port '%s'.", info.appId, info.vcc, info.app.runtime.port)

	local directories = fileSystem.GetVccAppDirectories(info.vcc, info.appId)

	local templateCommandLine = "nohup /usr/local/bin/rasa run --model %s --log-file %s/RUN.log --enable-api -p %s -v -vv < /dev/null > /dev/null 2>&1 &"
	local commandLine = templateCommandLine:format(
		directories.modelDir,
		directories.appVccDir,
		info.app.runtime.port
	)

	LogDebug("[RASA_COMMANDLINE:RunRasaApp] Running Rasa App Command:\n%s.", commandLine)
	os.execute(commandLine)

	local response = {result = "STARTING RASA MODEL INSTANCE"}
	return true, response
end

--[[

	sample:
		sh /usr/local/share/lua/5.1/rasa/helpers/rasa_run.sh -a start -vcc vcc1 -app app1 -l 1
]]--
function ExecuteShellRunRasaApp (info)
	assert(type(info) == "table")
	--LogDebug("[RASA_COMMANDLINE:ExecuteShellRunRasaApp] Execute Shell for Running Rasa App Info -> %s.", json.encode(info))
	assert(info.appId)
	assert(info.vcc)

	LogDebug("[RASA_COMMANDLINE:ExecuteShellRunRasaApp] Running Rasa App '%s', vcc '%s', port '%s'.", info.appId, info.vcc, info.app.runtime.port)

	-- sh /usr/local/share/lua/5.1/rasa/helpers/rasa_run.sh -a start -vcc vcc1 -app app -l 1
	local commandLine = ("sh /usr/local/share/lua/5.1/rasa/helpers/rasa_run.sh -a start -vcc %s -app %s -l 1"):format(
		info.vcc,
		info.appId
	)

	LogDebug("[RASA_COMMANDLINE:RunRExecuteShellRunRasaAppasaApp] Execute Shell Running Rasa App Command -> %s.", commandLine)
	os.execute(commandLine)

	local response = {result = "STARTING RASA MODEL INSTANCE"}
	return true, response
end

--[[
	sample:
		ps -ef | grep "rasa" | grep "/vcc1/rasaapp1" | grep -v "grep" | awk '{print $2}' > /vcc1/rasaapp1/runPid.txt
]]--
local function GetRasaAppPIDs (info)
	local directories = fileSystem.GetVccAppDirectories(info.vcc, info.appId)
	local fileName = "pid.txt"
	local fullFileName = ("%s%s"):format(directories.appVccDir, fileName)

	-- rasa train --config %s --out %s --domain %s --data %s > train_result.txt
	local commandLine = ([[ps -ef | grep "rasa" | grep "%s" | grep -v "grep" | awk '{print $2}' > %s]]):format(
		directories.appVccDir,
		fullFileName
	)

	--LogDebug("[RASA_COMMANDLINE:GetRasaAppPIDs] Get Rasa App PIDs Command -> %s.", commandLine)
	os.execute(commandLine)

	local success, contentFile = fileSystem.FileRead(fullFileName, "table")
	if not success then
		return false
	end

	return true, contentFile
end

--[[
	sample:
		pkill -9  RASA_APP_PID
]]--
function DownRasaApp (info)
	assert(type(info) == "table")
	--LogDebug("[RASA_COMMANDLINE:DownRasaApp] START going down RASA APP Info -> %s.", json.encode(info))
	assert(info.appId)
	assert(info.vcc)

	LogDebug("[RASA_COMMANDLINE:DownRasaApp] Down Rasa App '%s', vcc '%s'.", info.appId, info.vcc)

	local success, appPIDs = GetRasaAppPIDs(info)
	if not success then
		local err = {result = "UNABLE TO DOWN RASA APP - PID DOES NOT EXIST", info = info}
		LogDebug("[RASA_COMMANDLINE:DownRasaApp] Unable to Down Rasa App '%s', vcc '%s' PID does not exist.", info.appId, info.vcc)
		return false, err
	end

	for _, pid in ipairs(appPIDs) do
		pid = tonumber(pid)
		if type(pid) == "number" then
			-- kill -P 140496
			local commandLine = ("kill -9 %d"):format(pid)

			LogDebug("[RASA_COMMANDLINE:DownRasaApp] Down Rasa App Command -> %s.", commandLine)
			os.execute(commandLine)
		else
			LogDebug("[RASA_COMMANDLINE:DownRasaApp] Not a PID.", pid)
		end
	end

	local response = {}
	return true, response
end

--[[
	sample:
		pkill rasa
]]--
function StopRasa ()
	-- pkill rasa
	local commandLine = "pkill rasa"

	LogDebug("[RASA_COMMANDLINE:StopRasa] Stoping Rasa. Command -> %s.", commandLine)
	os.execute(commandLine)

	local response = {}
	return true, response
end

--[[
	Valida si ya existe una instancia de RASA para la App/Model
]]--
function IsRunningRasaApp (info)
	assert(type(info) == "table")
	--LogDebug("[RASA_COMMANDLINE:IsRunningRasaApp] Validating if a RASA instance exists for app Info -> %s.", json.encode(info))
	assert(info.appId)
	assert(info.vcc)

	local success, appPIDs = GetRasaAppPIDs(info)
	--LogDebug("[RASA_COMMANDLINE:IsRunningRasaApp] --> success: %s, appPIDs: %s", success, json.encode(appPIDs or {}))

	if not success then
		--LogDebug("[RASA_COMMANDLINE:IsRunningRasaApp] - There is no RASA instance for the App %s VCC %s.", info.appId, info.vcc)
		return false
	end

	if #appPIDs == 0 then
		--LogDebug("[RASA_COMMANDLINE:IsRunningRasaApp] + There is no RASA instance for the App %s VCC %s.", info.appId, info.vcc)
		return false
	end

	LogInfo("[RASA_COMMANDLINE:IsRunningRasaApp] RASA instance is running for the VCC '%s' App '%s'. PID: %s", info.vcc, info.appId, json.encode(appPIDs or {}))
	return true, appPIDs
end
