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 function GetBuffByName(unit, buffName)
	for i=1,40 do
		local name = UnitBuff(unit,i) 
		if buffName == name  then
			return UnitBuff(unit,i) 
		end			
	end
end

local function GetDebuffByName(unit, buffName)
	for i=1,40 do
		local name = UnitBuff(unit,i) 
		if buffName == name  then
			return UnitBuff(unit,i) 
		end			
	end
end

local expirationTime,count,unit,unit2
WhatsNext:AddConditionalStatement("Player Need Buff From Player",{
	category = "Buff",
	text = "{unit1} does not have {count} stack(s) of {buffName} from {unit2} or they will drop off within {time} seconds.",
	test = function(checkTable) 
		for i=1,40 do
			name, _, count, _, _, expirationTime, unit = UnitBuff(tostring(checkTable.unit1),i) 
			if WhatsNext: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,
	arguments = {
		unit1 = {label = "Unit 1",type = "unit", default = "target", possibleValues = WhatsNext.valueLists.unitAny},
		unit2 = {label = "Unit 2", type = "unit", default = "player", possibleValues = WhatsNext.valueLists.unitAny},
		buffName = {label = "Buff", type = "spell", default = ""},
		time = {label = "Seconds", type = "integer", default = 3, min=1,max=60},
		count = {label = "Stack Count",type = "integer", default = 1, min = 1, max = 100}
	}
})

WhatsNext:AddConditionalStatement("Player Need Buff",{
	category = "Buff",
	text = "{unit} does not have {count} stack(s) of {buffName} or they will drop off within {time} seconds.",
	test = function(checkTable) 
		for i=1,40 do
			name, _, count, _, _, expirationTime = UnitBuff(tostring(checkTable.unit),i) 
			if WhatsNext: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,
	arguments = {
		unit = {label = "Unit", type = "unit", default = "player", possibleValues = WhatsNext.valueLists.unitAny},
		buffName = {label = "Buff", type = "spell", default = ""},
		time = {label = "Seconds", type = "integer", default = 3, min = 1, max = 60},
		count = {label = "Stack Count", type = "integer", default = 1, min = 1, max = 100}
	}
})

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

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

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

WhatsNext:AddConditionalStatement("Target Need Debuff",{
	category = "Debuff",
	text = "{unit} does not have {count} stack(s) of {debuffName} or it will drop off within {time} seconds.",
	test = function(checkTable) 
		name, _, count, _, _, expirationTime  = GetDebuffByName(tostring(checkTable.unit), WhatsNext: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,
	arguments = {
		unit = {label = "Unit", type = "unit", default = "target", possibleValues = WhatsNext.valueLists.unitAny},
		debuffName = {label = "Debuff", type = "spell", default = ""},
		time = {label = "Seconds", type = "integer", default = 3, min = 1, max = 60},
		count = {label = "Stack Count", type = "integer", default = 1, min = 1, max = 100}
	}
})

WhatsNext:AddConditionalStatement("Target Has Debuff From Player",{
	category = "Debuff",
	text = "{unit1} has {count} stack(s) of the {debuffName} debuff from {unit2}.",
	test = function(checkTable)
		for i=1,40 do
			name, _, count, _, _, _, unit  = UnitDebuff(tostring(checkTable.unit1), i)
			if WhatsNext: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,
	arguments = {
		unit1 = {label = "Unit 1", type = "unit", default = "target", possibleValues = WhatsNext.valueLists.unitAny},
		unit2 = {label = "Unit 2", type = "unit", default = "player", possibleValues = WhatsNext.valueLists.unitAny},
		debuffName = {label = "Debuff", type = "spell", default = ""},
		count = {label = "Stack Count", type = "integer", default = 1, min = 1, max = 100}
	}
})


WhatsNext:AddConditionalStatement("Target Need Debuff From Player",{
	category = "Debuff",
	text = "{unit1} does not have {count} stack(s) of {debuffName} from {unit2} or they will drop off within {time} seconds.",
	test = function(checkTable) 
		for i=1,40 do
			name, _, count, _, _, expirationTime, unit  = UnitDebuff(tostring(checkTable.unit1), i)
			if name and WhatsNext: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,
	arguments = {
		unit1 = {label = "Unit 1", type = "unit", default = "target", possibleValues = WhatsNext.valueLists.unitAny},
		unit2 = {label = "Unit 2", type = "unit", default = "player", possibleValues = WhatsNext.valueLists.unitAny},
		debuffName = {label = "Debuff", type = "spell", default = ""},
		time = {label = "Seconds", type = "integer", default = 3, min = 1, max = 60},
		count = {label = "Stack Count", type = "integer", default = 1, min = 1, max = 100}
	}
})