Global("isPlayerInCombat", false)
Global("isPlayerInGroup", false)
Global("isPlayerSolo", true)
Global("isPlayerInRaid", false)
Global("isPlayerMounted", false)
Global("globalCooldownFinishedTimeStamp", nil)
Global("cooldowns", { })

group.IsPlayerInGroup = group.IsPlayerInGroup or group.IsCreatureInGroup
unit.IsInCombat = unit.IsInCombat or object.IsInCombat

function IsPlayerInCombat()
  local playerId = avatar.GetId()
  return unit.IsInCombat(playerId) or (unit.GetActivePet(playerId) ~= nil and avatar.IsPetInCombat())
end

function IsPlayerInGroup()
  return group.IsPlayerInGroup(avatar.GetId())
end

function IsPlayerSolo()
  return not IsPlayerInGroup() and not IsPlayerInRaid()
end

function IsPlayerInRaid()
  return raid.IsPlayerInAvatarsRaid(object.GetName(avatar.GetId()))
end

function IsPlayerMounted()
  return mount.GetActive() ~= nil
end

function IsGlobalCooldown()
  local counter = { }
  for k, v in cooldowns do
    counter[v] = (counter[v] or 0) + 1
  end
  
  for k, v in counter do
    if v >= 5 then
      return k
    end
  end

  return nil
end

function AddToCooldown(key, typ, duration)
  if key then
    cooldowns[key] = duration + cachedTimestamp
  end
end

function RemoveFromCooldown(key)
  if key then
    if not cooldowns[key] then
      for k, v in cooldowns do
        if type(k) == "number" or type(key) == "number" or k:IsEqual(key) then
          cooldowns[k] = nil
        end
      end
    else
      cooldowns[key] = nil
    end
  end
end

function PlayerStates()
  isPlayerInCombat = IsPlayerInCombat()
  isPlayerInGroup = IsPlayerInGroup()
  isPlayerSolo = IsPlayerSolo()
  isPlayerInRaid = IsPlayerInRaid()
  isPlayerMounted = IsPlayerMounted()
  globalCooldownFinishedTimeStamp = IsGlobalCooldown()
end