local nozzle = require "nozzle"

local function JSON_Encode (value)
	-- 1. JSON - enconde utilizando la rocka "JSON"
	local json = require "json"
	local ok, result = pcall(function (param)
			local resultJson = json.encode(param)
			if type(resultJson) == "string" then
				return resultJson
			else
				return param
			end
		end,
		value
	)

	if ok and result then
		-- OK el encode
		return result
	end

	-- 2. CJSON - enconde utilizando la rocka "CJSON"
	local cjson = require "cjson"
	ok, result = pcall(function (param)
			local resultJson = cjson.encode(param)
			if type(resultJson) == "string" then
				return resultJson
			else
				return false
			end
		end,
		value
	)

	return ok and result or nil
end

local function JSON_Decode (value)
	-- 1. JSON - desencodeo utilizando la rocka "JSON"
	local json = require "json"
	local ok, result = pcall (function ()
			local result = json.decode(value)
			if type(result) == "table" then
				return result
			else
				return value
			end
		end
	)

	if ok and result then
		-- OK el decode
		return result
	end

	-- 2. CJSON - desencodeo utilizando la rocka "CJSON"
	local cjson = require "cjson"
	local ok, result = pcall (function ()
			local result = cjson.decode(value)
			if type(result) == "table" then
				return result
			else
				return value
			end
		end
	)
	return ok and result or nil
end

local function json_validator(callback)
	callback = callback or function() end

	return nozzle.filter{
		name = "nozzle.stock.json_validator",
		input = function(self, web, ...)
			local post_data = web.input["post_data"]
			local request = JSON_Decode(post_data)
			if not request then
				local body = callback(web, post_data)
				if body then
					return body
				end
				web.status = 400
				web:content_type("text/plain")
				return "Invalid json input"
			end
			web.request = request
		end
	}
end

local function json_reply(callback)
	return nozzle.filter{
		name = "nozzle.stock.json_reply",
		output = function(self, web, output)
			web.headers["Content-Type"] = "application/json"
			if type(output) == "table" then
				return JSON_Encode(output)
			end
			return output
		end
	}
end

-- Returns a table with stock filters
return {
	json_validator = json_validator,
	json_reply     = json_reply
}

