public static bool IsCasting(this WoWUnit unit)
 {
     return(RotationCombatUtil.ExecuteActionOnUnit(unit, (luaUnitId) =>
     {
         string luaString = $@"return (UnitCastingInfo(""{luaUnitId}"") ~= nil or UnitChannelInfo(""{luaUnitId}"") ~= nil)";
         return Lua.LuaDoString <bool>(luaString);
     }));
 }
 public static bool HasMana(this WoWUnit unit)
 {
     return(RotationCombatUtil.ExecuteActionOnUnit(unit, (luaUnitId) =>
     {
         string luaString = $@"return (UnitPowerType(""{luaUnitId}"") == 0 and UnitMana(""{luaUnitId}"") > 1)";
         return Lua.LuaDoString <bool>(luaString);
     }));
 }
        public static bool CastingSpell(this WoWUnit unit, params string[] names)
        {
            return(RotationCombatUtil.ExecuteActionOnUnit(unit, (luaUnitId) =>
            {
                string luaString = $@"
	            local isCastingSpell = false;
	    
	            local name = UnitCastingInfo(""{luaUnitId}"")
	            if {LuaOrCondition(names, "name")} then
	                isCastingSpell = true
	            end
	            return isCastingSpell;"    ;
                return Lua.LuaDoString <bool>(luaString);
            }));
        }
     public static float CastingTimeLeft(this WoWUnit unit, string name)
     {
         return(RotationCombatUtil.ExecuteActionOnUnit(unit, (luaUnitId) =>
         {
             string luaString = $@"
         local castingTimeLeft = 0;
 
         local name, rank, displayName, icon, startTime, endTime, isTradeSkill = UnitCastingInfo(""{luaUnitId}"")
         if name == ""{name}"" then
             castingTimeLeft = endTime - GetTime()
         end
         return castingTimeLeft;";
             return Lua.LuaDoString <float>(luaString);
         }));
     }
        public static bool IsCreatureType(this WoWUnit unit, string creatureType)
        {
            if (_creatureTypeCache.ContainsKey(unit.Entry))
            {
                return(_creatureTypeCache[unit.Entry] == creatureType);
            }

            var type = RotationCombatUtil.ExecuteActionOnUnit(unit, (luaUnitId) =>
            {
                string luaString = $@"return UnitCreatureType(""{luaUnitId}"")";
                return(Lua.LuaDoString <string>(luaString));
            });

            _creatureTypeCache.Add(unit.Entry, type);
            return(type == creatureType);
        }
 public static bool HasDebuffType(this WoWUnit unit, string type)
 {
     return(RotationCombatUtil.ExecuteActionOnUnit(unit, (luaUnitId) =>
     {
         string luaString = $@"
         local hasDebuff = false;
         for i=1,40 do
             local name, rank, iconTexture, count, debuffType, duration, timeLeft = UnitDebuff(""{luaUnitId}"", i);
             if debuffType == ""{type}"" then
                 hasDebuff = true
                 break;
             end
         end
         return hasDebuff;";
         return Lua.LuaDoString <bool>(luaString);
     }));
 }
        public static bool HaveAnyDebuff(this WoWUnit unit, params string[] names)
        {
            return(RotationCombatUtil.ExecuteActionOnUnit(unit, (luaUnitId) =>
            {
                string luaString = $@"
		        local hasDebuff = false;
		        for i=1,40 do
			        local name, rank, iconTexture, count, debuffType, duration, timeLeft = UnitDebuff(""{luaUnitId}"", i);
		            if {LuaOrCondition(names, "name")} then
		                hasDebuff = true
		                break;
		            end
		        end
		        return hasDebuff;"        ;
                return Lua.LuaDoString <bool>(luaString);
            }));
        }
        /*
         * Example of NotifyForDelegate when usign COMBAT_TEXT_UPDATE instead of FocusUnit
         *
         *
         * public static void NotifyForDelegate(string id, List<string> args)
         * {
         *      lock (VerificationLock)
         *      {
         *              if (_delegateVerification?.Count > 0 && id == "COMBAT_TEXT_UPDATE" && _delegateVerification.Contains(args[0]))
         *              {
         *                      string eventName = args[0];
         *                      string auraOrHealerName = args[1];
         *
         *                      if (eventName.Contains("HEAL") && auraOrHealerName == RotationFramework.Me.Name)
         *                      {
         *                              Blindly.Run(() =>
         *                              {
         *                                      Thread.Sleep(Usefuls.Latency / 2);
         *                                      RotationLogger.Debug($"Clearing verification for {_verification.Item1} after delegated event {eventName}");
         *                                      _verification = EmptyVerify;
         *                                      _delegateVerification = new List<string>();
         *                              });
         *                      }
         *                      else if (eventName.Contains("AURA") && auraOrHealerName == _verification.Item1)
         *                      {
         *                              Blindly.Run(() =>
         *                              {
         *                                      Thread.Sleep(Usefuls.LatencyReal);
         *                                      RotationLogger.Debug($"Clearing verification for {_verification.Item1} after delegated event {eventName}");
         *                                      _verification = EmptyVerify;
         *                                      _delegateVerification = new List<string>();
         *                              });
         *
         *                      }
         *              }
         *      }
         * }
         */

        public static void ClearIfOutOfRange()
        {
            lock (_verificationLock)
            {
                if (_verification.Item1 != _emptyVerify.Item1)
                {
                    bool isInRange = RotationCombatUtil.ExecuteActionOnTarget(
                        _verification.Item2,
                        luaUnitId => Lua.LuaDoString <bool>($@"
                    local spellInRange = IsSpellInRange(""{_verification.Item1}"", ""{luaUnitId}"") == 1;
                    --DEFAULT_CHAT_FRAME:AddMessage(""Checking range of {_verification.Item1} on {luaUnitId} is "" .. (spellInRange and 'true' or 'false'));
                    return spellInRange;")
                        );

                    if (!isInRange && !RotationFramework.Me.IsCast)
                    {
                        RotationLogger.Debug($"Force clearing verification for {_verification.Item1} on {_verification.Item2} because we're out of range");
                        _verification = _emptyVerify;
                    }
                }
            }
        }
 public bool Execute(WoWUnit target, bool force = false)
 {
     return(RotationCombatUtil.CastSpell(this, target, force));
 }