--local custom = require "talkingDeadCustomLines"

zombieLine = {}
zombieLine.__index = zombieLine

-- A zombie line is a string with zero or more arguments that will replace the '%s' in the string. ("s%", lines) will result in picking one of the lines.
function zombieLine:new(line, ...)
	o = {}
	o.line = line
	o.args = {...}
	o.argNumber = select("#", ...)

    -- !! Inserting more lines later is going to break this unless you change metables!!
    -- The amount of possible resulting lines from the arguments.
    local c = 1
    for i,v in ipairs(o.args) do 
        c = c * #o.args[i] -- count += arg1 * arg2 * ... * argN 
    end 
    o.lineCount = c

	setmetatable(o, self)

	return o
end

local function pickRandom(wordList)
	--local index = math.random(1, #wordList)
	local index = ZombRandBetween(1, #wordList + 1)
	
	return wordList[index]
end

local function map(f, ...)
  local function helper(f, n, a, ...)
  if n > 0 then return f(a), helper(f, n-1, ...) end
  end

  return helper(f, select('#', ...), ...)
end

function zombieLine:getLine()
	if self.args == nil then
		return self.line
	else
		local a = {map(pickRandom, unpack (self.args) )}
		return string.format(self.line, unpack(a) ) 
	end
end


-- Currently does not allow for formatting. But that might be confusing to some anyway. Might add that later as an additional option.
local function handleCustom(linesTable, customList)
    if SandboxVars.LingeringVoices.CustomLines and #customList ~= 0 then
        table.insert( linesTable, zombieLine:new("%s", customList)) 
    end
end


------------------------------------------------------------------------------------------------------------------
-- Handles the reading of custom lines.

    -- Add all lines to a table through readline.
    -- Concat table.
    -- make a function of it with loadstring
    -- run function for result.

local function readCustomLines()
    local reader = getFileReader("talkingDeadCustomLines.lua", true)
    print ("fileREADER: ", reader)
    local lines = {}

    while true do
        local line = reader:readLine()

        if line then
            table.insert(lines, line)
        else 
            break
        end
    end

    print(lines)
    lines = table.concat(lines)
    print(lines)
    local func = loadstring(lines)
    local result = func()
    print("RESULT: ", result)
    return result

end

local custom = readCustomLines() -- custom lines

------------------------------------------------------------------------------------------------------------------
-- Possible way of making the line choice more balanced -- Not used atm.

bagOfLines = {}
bagOfLines.__index = bagOfLines

function bagOfLines:new(zombieLines) 
	o.zombieLines = zombieLines
	
	o.count = 0 -- total amount of lines, through combining all args.
	for i,line in ipairs(zombieLines) do
		local total = 1
		for j, arg in ipairs(line.args) do
			total = total * #arg
		end
		o.count = o.count + total
	end
	
	setmetatable(o, self)

	return o
end

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

--[[ 
        return tables of zombieLines. That way you can have different types of formatting even for lines for one situation. 
]]

local bodyWordList = { 
    "",
}

local statusList = {
	"",
}

local locationList = { -- End in a space please, so empty is also possible.
    "",
}

local activityList = {
    "",
}

local thingsToHate = {
    "",
}

local needs = {
    "",
}

local generalComplaints = {
	"",
}

local complaintBodyPain = zombieLine:new("%s", bodyWordList)
local complaintItch = zombieLine:new("%s", bodyWordList)
local complaints = zombieLine:new("%s", generalComplaints)
local activity = zombieLine:new("%s%s", locationList, activityList)
local iAm = zombieLine:new("%s", statusList)
local iHate = zombieLine:new("%s", thingsToHate)
local iNeed = zombieLine:new("%s", needs)


idleLines = { complaintBodyPain, complaintItch, complaints, activity, iAm, iHate, iNeed }


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

local lungeList = {
	"Hide...",
	"Run...",
	"Help us...",
	"Help me...",
    "...You",
    "YOU!...",
    "...STOP ME!",
    "...STOP US!",
    "...No",
    "NO...!",
    "Ahaha...",
    "Ahahaha...",
    "Haha... ha...",
}
lungeLines = { zombieLine:new("%s", lungeList) }

local staggerList = {
    "Ahaha...",
    "Ahahaha...",
    "Haha... ha...",
    "...No",
    "...No!",
    "...N-no",
	"...N-no!",
    "NO...!",
    "N-NO...!",
	"...Oh god",
    "OH GOD...",
    "Run...",
    "RUN!...",
    "I can't...",
    "...Wait!",
    "...Wait",
    "...W-wait",
    "WAIT!...",
    "W-WAIT!...",
    "...Please!",
    "...Please",
	"...P-please",
    "PLEASE!...",
    "P-PLEASE!...",
    "...Don't!",
    "...Don't",
    "...D-don't",
    "DON'T!...",
    "D-DON'T!...",
    "...You",
    "YOU!...",
    "...stop",
    "STOP!...",
}
staggerLines = { zombieLine:new("%s", staggerList) }


local fakeDeadList = {
	"...No",
    "...Run",
    "...Wait",
    "...Please",
    "Haha... ha...",
    "Ahaha...",
    "Ahahaha...",
    "...You",
}
fakeDeadLines = { zombieLine:new("%s", fakeDeadList) }

local thumpingList = {
	"H-hello...?",
	"...P-please",
    "...Open!",
    "OPEN!...",
    "...You",
    "Haha... ha...",
    "Ahaha...",
    "OPEN IT!...",
    "...Open it!",
    "Anyone...?",
}
thumpingLines = { zombieLine:new("%s", thumpingList) }


local attackList = {
	"I'm... sorry...",
	"...I ...can't",
	"...Please no...",
	"...S-stop me",
    "...Stop me!",
	"...Stop us",
	"...No ...no",
	"...No more",
    "...Help",
    "Help us...",
	"Help me...",
    "Run...",
    "...SOMEBODY!",
    "...ANYONE!",
    "Stay away...",
    "Stay awake...",
    "YOU!...",
    "...You",
    "...Wait",
    "...W-wait",
}
attackLines = { zombieLine:new("%s", attackList) }

if customLines and custom ~= nil then
    handleCustom(idleLines, custom.IdleList)
    handleCustom(lungeLines, custom.LungeList)
    handleCustom(staggerLines, custom.StaggerList)
    handleCustom(fakeDeadLines, custom.FakeDeadList)
    handleCustom(thumpingLines, custom.ThumpingList)
    handleCustom(attackLines, custom.AttackList )
end
