local _
local name, spellId, unit

local raidRanges, unitRange = {}
local rx, ry, px, py, zx1, zy1, zx2, zy2, dx, dy
local function GetRangeToRaidMember(unit)
	unitRange = raidRanges[unit] 
	if not unitRange then
		unitRange = { dist = 100000, time = 0}
		raidRanges[unit] = unitRange
	end
	if not WorldMapFrame:IsVisible() and unitRange.time < GetTime() then
		_, zx1, zy1, zx2, zy2 = GetCurrentMapZone();
		rx, ry = GetPlayerMapPosition(unit);
		px, py = GetPlayerMapPosition("player");
		if (rx == 0 and ry == 0) or (px == 0 and py == 0) or not ( zx1 and zx2 and zy1 and zy2) then
			unitRange.dist = 100000
		else
			dx,dy = math.abs(px - rx) * (zx1 - zx2), math.abs(py - ry) * (zy1 - zy2)
			unitRange.dist = math.sqrt(dx*dx + dy*dy)
		end
	end
	return unitRange.dist
end

local expirationTime,count,unit,unit2
WhatsNext:AddConditionalStatement("Player Need Buff From Player",{
	category = "Buff",
	test = function(checkTable) 
		for i=1,40 do
			name, _, _, count, _, _, expirationTime, unit = UnitBuff(tostring(checkTable.unit1),i) 
			if WN_GetSpellName(checkTable.buffName) == name and unit and UnitIsUnit(unit,tostring(checkTable.unit2)) then
				return math.max(count,1) < tonumber(checkTable.count or 1) or expirationTime - tonumber(checkTable.time) < GetTime()
			end			
		end
		return true
	end,
	text = function(checkTable) 
		return GetUnitDisplayText(checkTable.unit1) .. " does not have " .. tostring(checkTable.count or 1) .. " stack(s) of " .. WN_GetSpellName(checkTable.buffName) .. " from " .. GetUnitDisplayText(checkTable.unit2) .. " or they will drop off within " .. tostring(checkTable.time) .. " seconds." 
	end,
	arguments = {
		unit1 = {type = "dropdown", default = "target", possibleValues = WhatsNext.valueLists.unitAny},
		unit2 = {type = "dropdown", default = "player", possibleValues = WhatsNext.valueLists.unitAny},
		buffName = {type = "spell", default = ""},
		time = {type = "integer", default = 3},
		count = {type = "integer", default = 1}
	}
})

WhatsNext:AddConditionalStatement("Player Need Buff",{
	category = "Buff",
	test = function(checkTable) 
		for i=1,40 do
			name, _, _, count, _, _, expirationTime = UnitBuff(tostring(checkTable.unit),i) 
			if WN_GetSpellName(checkTable.buffName) == name then
				return math.max(count,1) < tonumber(checkTable.count or 1) or expirationTime - tonumber(checkTable.time) < GetTime()
			end			
		end
		return true
	end,
	text = function(checkTable) 
		return GetUnitDisplayText(checkTable.unit) .. " does not have " .. tostring(checkTable.count or 1) .. " stack(s) of " .. WN_GetSpellName(checkTable.buffName) .. " or they will drop off within " .. tostring(checkTable.time) .. " seconds." 
	end,
	arguments = {
		unit = {type = "dropdown", default = "player", possibleValues = WhatsNext.valueLists.unitAny},
		buffName = {type = "spell", default = ""},
		time = {type = "integer", default = 3},
		count = {type = "integer", default = 1}
	}
})

WhatsNext:AddConditionalStatement("Player Buffed",{
	category = "Buff",
	test = function(checkTable) 
		name, _, _, count, _, _, _, unit = UnitBuff(tostring(checkTable.unit), WN_GetSpellName(checkTable.buffName)) 
		return name and math.max(count,1) >=  tonumber(checkTable.count or 1) 
	end,
	text = function(checkTable) 
		return GetUnitDisplayText(checkTable.unit) .. " has " .. tostring(checkTable.count or 1) .. " stack(s) of the " .. WN_GetSpellName(checkTable.buffName) .. " buff."
	end,
	arguments = {
		unit = {type = "dropdown", default = "player", possibleValues = WhatsNext.valueLists.unitAny},
		buffName = {type = "spell", default = ""},
		count = {type = "integer", default = 1}
	}
})

WhatsNext:AddConditionalStatement("Player Buffed By Player",{
	category = "Buff",
	test = function(checkTable) 
		name, _, _, count, _, _, _, unit = UnitBuff(tostring(checkTable.unit1), WN_GetSpellName(checkTable.buffName)) 
		return name and unit and UnitIsUnit(unit,tostring(checkTable.unit2)) and math.max(count,1) >=  tonumber(checkTable.count or 1) 
	end,
	text = function(checkTable) 
		return GetUnitDisplayText(checkTable.unit1) .. " has " .. tostring(checkTable.count or 1) .. " stack(s) of the " .. WN_GetSpellName(checkTable.buffName) .. " buff from " .. GetUnitDisplayText(checkTable.unit2) .. "."
	end,
	arguments = {
		unit1 = {type = "dropdown", default = "player", possibleValues = WhatsNext.valueLists.unitAny},
		unit2 = {type = "dropdown", default = "player", possibleValues = WhatsNext.valueLists.unitAny},
		buffName = {type = "spell", default = ""},
		count = {type = "integer", default = 1}
	}
})

WhatsNext:AddConditionalStatement("Target Has Debuff",{
	category = "Debuff",
	test = function(checkTable)
		name, _, _, count, _, _, _  = UnitDebuff(tostring(checkTable.unit), WN_GetSpellName(checkTable.debuffName))
		return UnitName(tostring(checkTable.unit)) and name and math.max(count,1) >= tonumber(checkTable.count or 1)
	end,
	text = function(checkTable)
		return GetUnitDisplayText(checkTable.unit) .. " has " .. tostring(checkTable.count  or 1) .. " stack(s) of the " .. WN_GetSpellName(checkTable.debuffName) .. " debuff."
	end,
	arguments = {
		unit = {type = "dropdown", default = "target", possibleValues = WhatsNext.valueLists.unitAny},
		debuffName = {type = "spell", default = ""},
		count = {type = "integer", default = 1}
	}
})

WhatsNext:AddConditionalStatement("Target Need Debuff",{
	category = "Debuff",
	test = function(checkTable) 
		name, _, _, count, _, _, expirationTime  = UnitDebuff(tostring(checkTable.unit), WN_GetSpellName(checkTable.debuffName))
		return UnitName(tostring(checkTable.unit)) and (not name or (math.max(count,1) < tonumber(checkTable.count or 1)) or expirationTime - tonumber(checkTable.time) < GetTime())
	end,
	text = function(checkTable) 
		return GetUnitDisplayText(checkTable.unit) .. " does not have " .. tostring(checkTable.count or 1) .. " stack(s) of " .. WN_GetSpellName(checkTable.debuffName) .. " or it will drop off within " .. tostring(checkTable.time) .. " seconds." 
	end,
	arguments = {
		unit = {type = "dropdown", default = "target", possibleValues = WhatsNext.valueLists.unitAny},
		debuffName = {type = "spell", default = ""},
		time = {type = "integer", default = 3},
		count = {type = "integer", default = 1}
	}
})

WhatsNext:AddConditionalStatement("Target Has Debuff From Player",{
	category = "Debuff",
	test = function(checkTable)
		for i=1,40 do
			name, _, _, count, _, _, _, unit  = UnitDebuff(tostring(checkTable.unit1), i)
			if WN_GetSpellName(checkTable.debuffName) == name and unit and UnitIsUnit(unit,tostring(checkTable.unit2)) then
				return math.max(count,1) >= tonumber(checkTable.count or 1)
			end			
		end
	end,
	text = function(checkTable)
		return GetUnitDisplayText(checkTable.unit1) .. " has " .. tostring(checkTable.count  or 1) .. " stack(s) of the " .. WN_GetSpellName(checkTable.debuffName) .. " debuff from " .. GetUnitDisplayText(checkTable.unit2) .. "."
	end,
	arguments = {
		unit1 = {type = "dropdown", default = "target", possibleValues = WhatsNext.valueLists.unitAny},
		unit2 = {type = "dropdown", default = "player", possibleValues = WhatsNext.valueLists.unitAny},
		debuffName = {type = "spell", default = ""},
		count = {type = "integer", default = 1}
	}
})


WhatsNext:AddConditionalStatement("Target Need Debuff From Player",{
	category = "Debuff",
	test = function(checkTable) 
		for i=1,40 do
			name, _, _, count, _, _, expirationTime, unit  = UnitDebuff(tostring(checkTable.unit1), i)
			if name and WN_GetSpellName(checkTable.debuffName) == name and unit and UnitIsUnit(unit,tostring(checkTable.unit2)) then
				return math.max(count,1) < tonumber(checkTable.count or 1) or expirationTime - tonumber(checkTable.time) < GetTime()
			end			
		end
		return true
	end,
	text = function(checkTable) 
		return GetUnitDisplayText(checkTable.unit1) .. " does not have " .. tostring(checkTable.count or 1) .. " stack(s) of " .. WN_GetSpellName(checkTable.debuffName) .. " from " .. GetUnitDisplayText(checkTable.unit2) .. " or they will drop off within " .. tostring(checkTable.time) .. " seconds." 
	end,
	arguments = {
		unit1 = {type = "dropdown", default = "target", possibleValues = WhatsNext.valueLists.unitAny},
		unit2 = {type = "dropdown", default = "player", possibleValues = WhatsNext.valueLists.unitAny},
		debuffName = {type = "spell", default = ""},
		time = {type = "integer", default = 3},
		count = {type = "integer", default = 1}
	}
})

WhatsNext:AddConditionalStatement("Raid Buffed",{
	category = "Buff",
	test = function(checkTable) 
		if not UnitBuff("player", WN_GetSpellName(checkTable.buffName)) then
			return false
		end
		for i = 1,40 do
			unit = "raid"..i
			if UnitExists(unit) and GetRangeToRaidMember(i) <= tonumber(checkTable.yards) and not UnitBuff(unit, WN_GetSpellName(checkTable.buffName)) then
				return false
			end				
		end
		return true
	end,
	text = function(checkTable) 
		return "all raid members in " .. tostring(checkTable.yards) .. " yards have the " .. WN_GetSpellName(checkTable.buffName) .. " buff."
	end,
	arguments = {
		buffName = {type = "spell", default = ""},
		yards = {type = "integer", default = 1}
	}
})

WhatsNext:AddConditionalStatement("Raid Buffed By Player",{
	category = "Buff",
	test = function(checkTable)
		name, _, _, _, _, _, _, unit = UnitBuff("player", WN_GetSpellName(checkTable.buffName)) 
		if not name or not unit or not UnitIsUnit(unit,tostring(checkTable.unit)) then
			return false
		end	
		for i = 1,40 do
			unit2 = "raid"..i
			if UnitExists(unit2) then
				name, _, _, _, _, _, _, unit = UnitBuff(unit2, WN_GetSpellName(checkTable.buffName)) 
				if GetRangeToRaidMember(unit2) <= tonumber(checkTable.yards) and (not name or not unit or not UnitIsUnit(unit,tostring(checkTable.unit))) then
					return false
				end				
			end
		end
		return true
	end,
	text = function(checkTable) 
		return "all raid members in " .. tostring(checkTable.yards) .. " yards have the " .. WN_GetSpellName(checkTable.buffName) .. " buff from " .. GetUnitDisplayText(checkTable.unit) .. "."
	end,
	arguments = {
		unit = {type = "dropdown", default = "player", possibleValues = WhatsNext.valueLists.unitAny},
		buffName = {type = "spell", default = ""},
		yards = {type = "integer", default = 1}
	}
})

WhatsNext:AddConditionalStatement("Raid Debuffed",{
	category = "Debuff",
	test = function(checkTable) 
		if not UnitDebuff("player", WN_GetSpellName(checkTable.debuffName)) then
			return false
		end
		for i = 1,40 do
			local raidUnit = "raid"..i
			if UnitExists(raidUnit) and GetRangeToRaidMember(i) <= tonumber(checkTable.yards) and not UnitDebuff(raidUnit, WN_GetSpellName(checkTable.debuffName)) then
				return false
			end				
		end
		return true
	end,
	text = function(checkTable) 
		return "all raid members in " .. tostring(checkTable.yards) .. " yards have the " .. WN_GetSpellName(checkTable.debuffName) .. " debuff."
	end,
	arguments = {
		debuffName = {type = "spell", default = ""},
		yards = {type = "integer", default = 1}
	}
})

WhatsNext:AddConditionalStatement("Raid Debuffed By Player",{
	category = "Debuff",
	test = function(checkTable)
		name, _, _, _, _, _, _, unit = UnitDebuff("player", WN_GetSpellName(checkTable.debuffName)) 
		if not name or not unit or not UnitIsUnit(unit,tostring(checkTable.unit)) then
			return false
		end	
		for i = 1,40 do
			local raidUnit = "raid"..i
			if UnitExists(raidUnit) then
				local name, _, _, _, _, _, _, unit = UnitDebuff(raidUnit, WN_GetSpellName(checkTable.debuffName)) 
				if GetRangeToRaidMember(raidUnit) <= tonumber(checkTable.yards) and (not name or not unit or not UnitIsUnit(unit,tostring(checkTable.unit))) then
					return false
				end				
			end
		end
		return true
	end,
	text = function(checkTable) 
		return "all raid members in " .. tostring(checkTable.yards) .. " yards have the " .. WN_GetSpellName(checkTable.debuffName) .. " debuff from " .. GetUnitDisplayText(checkTable.unit) .. "."
	end,
	arguments = {
		unit = {type = "dropdown", default = "player", possibleValues = WhatsNext.valueLists.unitAny},
		debuffName = {type = "spell", default = ""},
		yards = {type = "integer", default = 1}
	}
})