module(..., package.seeall);
local utf8 = require "icu.utf8"
local cassandra = require "lua_cassandra"

--==============================================================================
function capitalizeFirst(s)
	return string.upper(s:sub(1,1)) .. s:sub(2)
end
--==============================================================================
-- removes whitespaces from left and right of the string parameter.
--
-- from: http://snippets.luacode.org/?p=snippets/trim_whitespace_from_string_76
-- "These functions remove whitespace from the left, right, or both sides of a
-- string. The implementations below are nearly optimal for Lua pattern
-- implementations yet also kept simple, so these are recommended for most
-- situations. Somewhat higher performance may be obtained from Lpeg
-- implementations, and a few times higher performance may be obtained from C
-- implementations."
function trim(s)
	return s:find('^%s*$') and '' or s:match('^%s*(.*%S)')
end

--==============================================================================
function getCFNameFromFields(documentName, fields)
	local capitalizedDocumentName = capitalizeFirst(documentName)

	if type(fields) == "table" then
		local capitalizedFields = {}
		for _, field in pairs(fields) do
			table.insert(capitalizedFields, capitalizeFirst(field))
		end
		cfName = capitalizedDocumentName .. "By" .. table.concat(capitalizedFields, "And")
	else
		cfName = capitalizedDocumentName .. "By" .. capitalizeFirst(fields)
	end

	return cfName
end

function getCFNameDirectIndex(documentName)
	return capitalizeFirst(documentName) .. "DirectIndex"
end

function getCFNameDetailsIndex(documentName)
	return capitalizeFirst(documentName) .. "DetailsIndex"
end

function getCFNameTerms(documentName)
	return capitalizeFirst(documentName) .. "Terms"
end

--==============================================================================
function isValidAsValue(value)
	return type(value) == "string" and value ~= ""
end
--==============================================================================
function getSortFieldValue(documentDefinition, document)
	local sortField = documentDefinition.sortField
	if not sortField then
		return nil, "there is no sortField"
	end
	local sortFieldValue = document[sortField]
	if not sortFieldValue then
		return nil, "there is no '" .. tostring(sortField) .. "'' in document"
	end

	return trim(icu.utf8.lower(tostring(sortFieldValue)))
end
--==============================================================================
function translateToReverseOrder(orderString)
	local reverseOrder = nil
	if orderString == "desc" then
		reverseOrder = true
	elseif orderString == "asc" or orderString == nil then
		reverseOrder = false
	end
	if reverseOrder == nil then
		return nil, "illegal order, it should be \"asc\", \"desc\" or nil "
	end
	return reverseOrder
end
--==============================================================================
-- from a composite column name returns sortField and unique from a composite
-- column name from the indexes. since names are a composition of tokens,
-- sortFieldValue and unique, in that order. SortFieldPosition
function getSortFieldAndUnique(composite, sortFieldPosition)
	local c = cassandra.Composite:new(composite)
	for i = 1, sortFieldPosition do
		c:GetString()
	end
	return c:GetString(), c:GetString()
end
--==============================================================================
local function compareHandles(a, b, sortFieldPosition)
	local sortFieldA, uniqueA = getSortFieldAndUnique(a, sortFieldPosition)
	local sortFieldB, uniqueB = getSortFieldAndUnique(b, sortFieldPosition)

	-- when sortfields are equal, first test uniqueA and uniqueB for equality
	-- since they can be nil (and comparision of nil values throws an error)

	if sortFieldA < sortFieldB then return 1
	elseif sortFieldA > sortFieldB then return -1
	elseif uniqueA == uniqueB then return 0
	elseif uniqueA < uniqueB then return 1
	elseif uniqueA > uniqueB then return -1
	else return 0
	end
end
--==============================================================================
function getHandleComparator(reverse, sortFieldPosition)
	return
		function(a,b)
			return compareHandles(unpack(reverse and {b, a, sortFieldPosition} or {a, b, sortFieldPosition}))
		end
end
--==============================================================================
function isForbiddenComposite(composite, forbiddenComposites)

	if not forbiddenComposites then
		return false
	end

	for _, index in ipairs(composite) do
		if forbiddenComposites[index] then
			for _, companion in ipairs(composite) do
				for _, element in ipairs(forbiddenComposites[index]) do
					if element == companion then
						return true
					end
				end
			end
		end
	end
	return false
end
--==============================================================================
