
local DAMAGE_TAKEN_MEMORY_LENGTH = 4
local EARLY_CAST_EXPIRE_MARGIN = 3
local MINIMUM_TIME_BETWEEN_INTERRUPTS = .3

local checks = {}
local checkResults = {}
local categories = {}
local temp,temp2 = {},{}
local checkTexts = {}
function WhatsNext:AddConditionalStatement(checkName,checkBlock)
	wipe(categories)
	checks[checkName] = checkBlock
end

function WhatsNext:RemoveConditionalStatement(checkName)
	wipe(categories)
	checks[checkName] = nil
end

function WhatsNext:ContainsConditionalStatement(checkName)
	return checks[checkName] ~= nil
end

function WhatsNext:GetConditionalStatement(checkName)
	return checks[checkName]
end

function WhatsNext:SetupTestChecks()
	wipe(checkTexts)
	WhatsNext:ResetTestChecks()
end

local _,x,y,check
function WhatsNext:ResetTestChecks()
	wipe(checkResults)
	if not WorldMapFrame:IsVisible() then
		x,y = GetPlayerMapPosition("player")
		if x == 0 and y == 0 then
			SetMapToCurrentZone() 
		end
	end
end

function WhatsNext:TestCheck(checkTable)
	if not checkResults[self:GetCheckText(checkTable)] then
		check = checks[checkTable.type]
		for arg,argTable in pairs(check.arguments) do
			if not checkTable[arg] then
				checkTable[arg] = argTable.default
			end
		end
		if checks[checkTable.type].test(checkTable) then
			checkResults[self:GetCheckText(checkTable)] = checkTable.invert and 0 or 1
		else
			checkResults[self:GetCheckText(checkTable)] = checkTable.invert and 1 or 0
		end
	end
	return checkResults[self:GetCheckText(checkTable)] == 1
end

function WhatsNext:TestChecks(checkList)
	if checkList then
		for i,checkTable in ipairs(checkList) do
			if not self:TestCheck(checkTable) then
				return false
			end
		end
	end
	return true
end

function WhatsNext:GetArguments(checkType)
	if checks[checkType] then
		return checks[checkType].arguments
	end
end

function WhatsNext:GetCheckText(checkTable)
	if checkTexts[checkTable] then
		return checkTexts[checkTable] 
	end
	check = checks[checkTable.type]
	if check then
		for arg,argTable in pairs(check.arguments) do
			if not checkTable[arg] then
				checkTable[arg] = argTable.default
			end
		end
		checkTexts[checkTable] = (checkTable.invert and "Not if " or "If ") .. check.text(checkTable)
		return checkTexts[checkTable]
	end
	return ""
end

function WhatsNext:GetSampleCheckTexts(category)
	wipe(temp)
	for checkType, check in pairs(checks) do
		if not category or category == check.category then
			temp[checkType] = self:GetSampleCheckText(checkType)
		end
	end
	return temp
end

function WhatsNext:GetCheckCategories()
	if #categories == 0 then
		for type, check in pairs(checks) do
			 if not tContains(categories,check.category) then
				tinsert(categories,check.category)
			 end
		end
		sort(categories,function(a,b)
			return a < b
		end)
	end
	return categories
end

function WhatsNext:GetSampleCheckText(checkType)
	check = checks[checkType]
	if not check then
		return ""
	end
	wipe(temp2)
	for var,varType in pairs(check.arguments) do
		temp2[var] = "{"..var.."}"
	end
	return  "If " .. check.text(temp2)
end


function WN_GetSpellName(spell)
	return tonumber(spell) and GetSpellInfo(spell) or spell
end


function UnitBuffByID(unit,buffID)
	for i = 1,40 do
		name, _, _, _, _, _, _, _, _, _, spellId = UnitBuff(unit, i) 
		if not name then
			return
		end
		if name and tonumber(spellId) == tonumber(buffID) then
			return UnitBuff(unit, i) 
		end
	end
end
