local utf8 = require "icu.utf8"

module((...), package.seeall)


local canonize = function (word)
	map = {
		["á"]="a", ["é"]="e", ["í"]="i", ["ó"]="o", ["ú"]="u",
		["à"]="a", ["è"]="e", ["ì"]="i", ["ò"]="o",	["ù"]="u",
		["ä"]="a", ["ë"]="e", ["ï"]="i", ["ö"]="o", ["ü"]="u",
		["â"]="a", ["ê"]="e", ["î"]="i", ["ô"]="o",	["û"]="u",
		["ã"]="a", 						 ["õ"]="o",
		["ñ"]="ni",
	}
	local normalized = utf8.gsub(word, "%!a", map)
	
	local codepoints = {utf8.codepoint(normalized, 1, -1)}
	local lastCodepoint
	local newCodepoints = {}
	for _,cp in ipairs (codepoints) do
		if cp ~= lastCodepoint then
			table.insert(newCodepoints, cp)
		end
		lastCodepoint = cp
	end
	
	local canonized = utf8.char(unpack(newCodepoints))
	
	return canonized
end

--Loads and return the feelings words from the specified path
--The caller must keep this table in order to use the detect feature
--If path is not specified, then it loads the default file
function LoadWords (path, wordsParam)

	local words
	if path == nil then
		local full = debug.getinfo(1, "S").source:match("^@(.+)")
		path = string.match(full, "^(.*)[/\\]([^/\\]*)$") .. "/feelingsDetector/feelingsWords.txt"
	end

	if not wordsParam or next(wordsParam) == nil then
		words = dofile(path)
	else
		words = wordsParam
	end
	
	--assumes it has been preprocessed in feelingWordsBuilder.lua
	return words
end


local emoticonsToHash = function(str)
	local hash = {}
	utf8.gsub(str, "%S+", function (w)
		hash[w] = true
	end)
	return hash
end

local emoticons = {
	["+"] = emoticonsToHash ":-) :) :o) :] :c) :> =] 8) =) :} :^) ツ :d :-d 8-d 8d x-d xd =d ;-) ;) *-) ;-] ;] ;d :p :-p",
	["-"] = emoticonsToHash ":-( :( :-c :-< :< :-[ :[ :{ :'( :'[ :'{ wtf",
}

--Try to detect the feelings of the given text, based in the words supplied
function DetectFeelings (text, language, dictionary)

	assert (type (text) == "string", "first parameter must be a utf-8 encoded string")
	assert (type (language) == "string", "second parameter must be a string representing the language")
	assert (type (dictionary) == "table", "third parameter must be a table created with the function LoadWords")

	function splitWords(str)
		local t = {}
		local function aux(word)
			table.insert(t, word)
			return ""
		end
		icu.utf8.gsub(text, "[%!a]+", aux)
		return t
	end

	function countLanguageWords (words, languageWords)
		local count = 0	
		for _, w in ipairs (words) do
			local word = canonize (w)
			if languageWords[word] then
				count = count + languageWords[word]
			end
		end
		return count
	end
	
	function countEmoticons (lower, sign)
		local total = 0
		--pattern "%S+" fails in some cases
		utf8.gsub(lower, "[^ \t\r\n]+", function (w)
			if emoticons[sign][w] then
				total = total + 1
			end
		end)
		return total
	end
	
	if dictionary[language] == nil then
		return nil
	end
	
	local lower = utf8.lower (text)
	
	if lower == nil then
		return nil
	end
	
	local words = splitWords (lower)
	
	local bestSign = ""
	local bestCount = 0
	local totalCount = 0

	for sign, signWords in pairs (dictionary[language]) do
		local count = countLanguageWords (words, signWords)
		local emoticons = countEmoticons (lower, sign)
		
		count = count + emoticons * 3
		totalCount = totalCount + count
		if count > bestCount then
			bestCount = count
			bestSign = sign
		end
	end
	
	if bestSign == "" then
		return nil
	else
		local percent = bestCount / totalCount
		
		if percent < 0.7 then
			--only predicts feelings when we are at least 70% sure
			return nil
		end
		
		return bestSign, percent
	end
end
