module(..., package.seeall)

-- in case it's available
local LogInfo = LogInfo or function(msg, ...)
	print("Info", msg:format(...))
end
local LogWarning = LogWarning or function(msg, ...)
	print("Warning", msg:format(...))
end

local function GetSchedulerModule ()
	local scheduler = require("reporter.scheduler")
	return scheduler
end

--[[
	Asigna puerto por defecto si es que no existe uno.
]]--
local function MakePort (protocolConfig)
	assert(protocolConfig)
	return protocolConfig.Port or 22 -- default port
end

--[[
	Funcion que elimina la pwd del log a visualizar.
]]--
local function SanitizePwd (command, protocolConfig)
	if not command or not protocolConfig and protocolConfig.Pwd then
		return ""
	end
	local startPos, endPos = string.find(command, protocolConfig.Pwd)
	if not startPos then
		return ""
	end
	local startText = string.sub(command, 1, startPos - 1)
	local endText = string.sub(command, endPos + 1)
	return ("%s********************%s"):format(startText, endText)
end

--[[
	Como Curl me envia códigos de error, aca agrego los errores conocidos con su descripción.
]]--
local function GetError (codeErr, action)
	local defaultErr = "Unrecognized Error"
	if not codeErr then
		return defaultErr
	end

	local errors = {
		["1792"]  = "Unable to connect, invalid Port.",
		["5376"]  = {
			["create directory"] = "Unable to create directory. Directory already exist.",
			["remove directory"] = "Unable to remove directory. Directory does not exist."
		},
		["17152"] = "Unable to connect, invalid Connection Information."
	}

	codeErr = tostring(codeErr)
	local msgErr = errors[codeErr] or defaultErr
	if type(msgErr) == "table" then
		action = action or ""
		msgErr = msgErr[action] or defaultErr
	end

	return ("%s - Code: %s"):format(msgErr, codeErr)
end

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

--[[
	Aca se realiza la creacion del directorio destino en SFTP, en el cual se subiran los archivos.
]]--
function CreateDirectory (parentDirectory, directory, protocolConfig)
	--LogInfo("[SFTP:CreateDirectory] Create directory on SFTP. Directory '%s', parent directory: '%s'.", directory, parentDirectory)

	if not directory or directory:len() == 0 then
		return true
	end

	parentDirectory = parentDirectory or ""
	if parentDirectory:len() > 0 then
		directory = parentDirectory .. "/" .. directory
	end

	-- curl -k -v 'sftp://root:password@192.168.4.11:22/' -Q '-MKDIR /borrame1' --ftp-create-dirs
	-- curl -k -v 'sftp://root:password@192.168.4.11:22/borrame/' -Q '-MKDIR /borrame/mynewdir' --ftp-create-dirs

	local templateCommand = [[curl -k -v 'sftp://%s:%s@%s:%s/' -Q '-MKDIR %s' --ftp-create-dirs]]
	local command = templateCommand:format(protocolConfig.User, protocolConfig.Pwd, protocolConfig.Host, MakePort(protocolConfig), directory)

	--local logCommand = SanitizePwd(command, protocolConfig)
	--LogInfo("[SFTP:CreateDirectory] Curl command Create Directory SFTP: %s", logCommand)

	local res = os.execute(command)
	--LogDebug("command: %s", command)
	--LogDebug("[SFTP:CreateDirectory] ---> Curl command res: '%s'", res)

	local success = tonumber(res) == 0
	local err
	if not success then
		err = GetError(res, "create directory")
		--LogWarning("[SFTP:CreateDirectory] Error creating directory '%s' to SFTP. Err: '%s', SFTP host: '%s'.", directory, err, protocolConfig.Host)
	end

	return success, err
end

--[[
	Aca se realiza el borrado de un directorio del FTP.
]]--
function RemoveDirectory (parentDirectory, directory, protocolConfig)
	LogInfo("[SFTP:RemoveDirectory] Removing directory on SFTP. Directory '%s', parent directory: '%s'.", directory, parentDirectory)

	if not directory or directory:len() == 0 then
		return true
	end
	if parentDirectory and parentDirectory:len() > 0 then
		directory = parentDirectory .. "/" .. directory
	end

	-- curl -k -v 'sftp://root:Inc0nc3rt!@192.168.4.11:22/borrame/mynewdir/' -Q '-RMDIR /borrame/mynewdir' --ftp-create-dirs
	--
	local templateCommand = [[curl -k -v 'sftp://%s:%s@%s:%s/%s/' -Q '-RMDIR %s' --ftp-create-dirs]]
	local command = templateCommand:format(protocolConfig.User, protocolConfig.Pwd, protocolConfig.Host, MakePort(protocolConfig), parentDirectory, directory)

	--local logCommand = SanitizePwd(command, protocolConfig)
	--LogDebug("[SFTP:RemoveDirectory] Curl command Remove Directory SFTP: %s", logCommand)

	local res = os.execute(command)
	--LogDebug("command: %s", command)
	--LogDebug("[SFTP:RemoveDirectory] ---> Curl command res: '%s'", res)

	local success = tonumber(res) == 0
	local err
	if not success then
		err = GetError(res, "remove directory")
		LogWarning("[SFTP:RemoveDirectory] Error Removing directory '%s' to SFTP. Err: '%s', SFTP Host: '%s'.", directory, err, protocolConfig.Host)
	end

	return success, err
end

--[[
	Aca se realiza el UPLOAD del arhivo al SFTP.
	El archivo se procesa en forma de BLOB o de string.
]]--
function UploadFile (fileName, content, fileType, protocolConfig, rootDirectory, scheduleToRun, utils, entry)
	local localFile = entry

	if rootDirectory and rootDirectory:len() > 0 then
		fileName = rootDirectory .. "/" .. fileName
	end

	-- curl -k -v 'sftp://root:Inc0nc3rt!@192.168.4.11:22/borrame/emmita26072017_B.txt' -T '/tmp/emma1.txt'

	local templateCommand = [[curl -k -v 'sftp://%s:%s@%s:%s/%s' -T '/%s']]
	local command = templateCommand:format(protocolConfig.User, protocolConfig.Pwd, protocolConfig.Host, MakePort(protocolConfig), fileName, localFile)

--	local logCommand = SanitizePwd(command, protocolConfig)
--	LogDebug("[SFTP:SecureFTPUploadFile] Curl command Upload File SFTP: %s", logCommand)
	local res = os.execute(command)
	--LogDebug("command: %s", command)
	--LogDebug("[SFTP:SecureFTPUploadFile] ---> Curl command res: '%s'", res)

	local success = tonumber(res) == 0
	local err
	if not success then
		err = GetError(res)
		LogError("[SFTP:SecureFTPUploadFile] Error uploading file '%s' to SFTP. Err: '%s', SFTP host: '%s'.", fileName, err, protocolConfig.Host)
	end

	return success, err
end


--[[
	Funcion que valida si el FTP esta listo para ser utilizado.
	Conexion basica contra el host, user y password.
]]--
function IsReady (schedule)
	local protocolConfig = schedule.sftp or {}

	LogInfo("[SFTP:IsReady] Validate connection to SFTP. SFTP host: '%s'.", protocolConfig.Host)
	--LogDebug("[SFTP:IsReady] ---> Schedule config: '%s'.", json.encode(schedule))

	if not protocolConfig.Host then
		LogError("[SFTP:IsReady] SFTP host is required.")
		return false, "Incomplete definition. FTP host is required."
	end
	if not protocolConfig.User then
		LogError("[SFTP:IsReady] SFTP user is required.")
		return false, "Incomplete definition. FTP user is required."
	end
	if not protocolConfig.Pwd then
		LogError("[SFTP:IsReady] SFTP pwd is required.")
		return false, "Incomplete definition. FTP pwd file is required."
	end

	-- curl -k 'sftp://192.168.4.11:22/' --user 'root:'lacontrasena'
	local templateCommand = [[curl -k 'sftp://%s:%s/' --user '%s:%s']]
	local command = templateCommand:format(protocolConfig.Host, MakePort(protocolConfig), protocolConfig.User, protocolConfig.Pwd)

	--local logCommand = SanitizePwd(command, protocolConfig)
	--LogDebug("[SFTP:IsReady] Curl command is ready SFTP: %s", logCommand)
	local res = os.execute(command)
	--LogDebug("command: %s", command)
	--LogDebug("[SFTP:IsReady] ---> Curl command res: '%s'", res)

	if tonumber(res) ~= 0 then
		local err = GetError(res)
		LogError("[SFTP:IsReady] Connection error to SFTP. Err: '%s', SFTP host: '%s'.", err, protocolConfig.Host)
		return false, err
	end

	LogInfo("[SFTP:IsReady]--> Successful connection to SFTP host: '%s'. SFTP Response: **************", protocolConfig.Host)

	return true
end

--[[
	Funcion que valida si se puede escribir en el directorio destino del SFTP.
]]--
function WriteValidation (schedule, rootDestinationDirectory)
	local protocolConfig = schedule.sftp or {}

	LogInfo("[SFTP:WriteValidation] Write validation connection to SFTP. SFTP host: '%s', rootDestinationDirectory: '%s'.", protocolConfig.Host, rootDestinationDirectory)
	--LogDebug("[SFTP:WriteValidation] ---> Schedule config: '%s'.", json.encode(schedule))

	local tempDir = "__TMP_" .. uuid.new()
	local success, err = CreateDirectory(rootDestinationDirectory, tempDir, protocolConfig)

	if not success then
		LogInfo("[SFTP:WriteValidation] Not have write permissions on SFTP. Msg: '%s', SFTP Host: '%s'.", err, protocolConfig.Host)
		return false, "Not have write permissions on SFTP"
	end

	RemoveDirectory(rootDestinationDirectory, tempDir, protocolConfig)
	return true
end