module(..., package.seeall)
require("socket")
require("md5")
local m_url = require("socket.url")
local json = require("json")
local m_request = require "helpers.request"

----------------------------------------------------------------------------
-- PRIVATED functions
----------------------------------------------------------------------------

local m_cookie, m_serverIP, m_serverPort

--[[

]]--
local function SetCookie (c)
	m_cookie = c
end

--[[

]]--
local function RequestCallbackError ()
	Logout()
end

--[[

]]--
local function LoginUser (username, callcenterId, password, token, applicationName)
	assert(type(username) == "string")
	assert(type(callcenterId) == "string")
	assert(type(password) == "string")
	assert(type(applicationName) == "string")
	assert(type(token) == "table")
	if type(token.loginToken) ~= "string" then
		return false, "INVALID TOKEN"
	end
	local textToEncode = string.lower(username) .. password
	local hash = md5.sumhexa(md5.sumhexa(textToEncode) .. token.loginToken)
	local params = string.format("hash=%s&username=%s&loginToken=%s&callcenter=%s&app=%s", hash, m_url.escape(username), token.loginToken, callcenterId, m_url.escape(applicationName))
	local url = "agent/login/authenticate/"
	local headers = {
		['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8'
	}
	local fullUrl = BuildCompleteUrl(url)
	local result, encodedResponse = m_request.Post(fullUrl, params, headers, m_cookie, RequestCallbackError)
	--print(string.format("[LoginUser] result: '%s', encodedResponse: %s.", tostring(result), tostring(encodedResponse)))
	if not result then
		-- ERROR
		encodedResponse = encodedResponse or "UNRECOGNIZED ERROR"
		print("[LoginUser] 1->Error logging in: ".. tostring(encodedResponse))
		return false, encodedResponse
	end
	local data = json.decode(encodedResponse)
	if not data.status then
		print("[LoginUser] 2-> Error logging in: ".. tostring(encodedResponse))
		return false, encodedResponse
	end
	-- OK
	m_cookie = "AUTH_SID_AGENT=".. data.authToken
	SetCookie(m_cookie)
	return true
end

----------------------------------------------------------------------------
-- EXPORTED functions
----------------------------------------------------------------------------
function BuildCompleteUrl (url, serverIP, serverPort)
	assert(type(url) == "string")
	serverIP = serverIP or m_serverIP
	serverPort = serverPort or m_serverPort
	return string.format("http://%s:%s/inconcert/apps/%s", serverIP, serverPort, url)
end

--[[

]]--
function GetCookie ()
	return m_cookie
end

--[[

]]--
function SetServerAndPort (serverIP, portIP)
	m_serverIP = serverIP or "localhost"
	m_serverPort = portIP or "8082"
end

--[[

]]--
function Login (user, vcc, password, application)
	assert(type(user) == "string")
	assert(type(vcc) == "string")
	assert(type(password) == "string")
	assert(type(application) == "string")
	local params = string.format("username=%s&callcenter=%s&", m_url.escape(user), vcc)
	local url = "agent/login/getToken/"
	local headers = {
		['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8'
	}
	local fullUrl = BuildCompleteUrl(url)
	local response, tokenResponse =  m_request.Post(fullUrl, params, headers, nil, RequestCallbackError) 
	--print("[Login] GET TOKEN RESPONSE: " .. tostring(tokenResponse))
	if response then
		-- ok
		local response = json.decode(tokenResponse)
		local result, reason = LoginUser(user, vcc, password, response, application)
		return result, reason
	end
	-- error
	print("Error getting token: ".. tostring(tokenResponse))
	return false, "Error getting token: ".. tostring(tokenResponse)
end

--[[

]]--
function LoginSystemUser (user, password)
	-- default values
	user = user or "deployer"
	vcc = "system"
	password = password or "11111111"
	return Login(user, vcc, password, "agent")
end

--[[

]]--
function Logout ()
	--print("Logout")
	local fullUrl = BuildCompleteUrl("agent/login/logout/")
	local result = m_request.Post(fullUrl, nil, nil, m_cookie)
	SetCookie(nil)
	return result
end
