using System;
using System.Collections.Generic;
using System.Text;
using Server.Factions;
using Server.Items;
using Server.Network;
using Server.Regions;

namespace Server.Engines.ConPVP
{
    public enum TournamentStage
    {
        Inactive,
        Signup,
        Fighting
    }

    public enum GroupingType
    {
        HighVsLow,
        Nearest,
        Random
    }

    public enum TieType
    {
        Random,
        Highest,
        Lowest,
        FullElimination,
        FullAdvancement
    }

    public enum TourneyType
    {
        Standard,
        FreeForAll,
        RandomTeam,
        RedVsBlue,
        Faction
    }

    [PropertyObject]
    public class Tournament
    {
        private static readonly TimeSpan SliceInterval = TimeSpan.FromSeconds(12.0);
        private int m_ParticipantsPerMatch;
        private int m_PlayersPerParticipant;

        public Tournament(IGenericReader reader)
        {
            var version = reader.ReadEncodedInt();

            switch (version)
            {
                case 5:
                    {
                        FactionRestricted = reader.ReadBool();

                        goto case 4;
                    }
                case 4:
                    {
                        EventController = reader.ReadEntity<EventController>();

                        goto case 3;
                    }
                case 3:
                    {
                        SuddenDeathRounds = reader.ReadEncodedInt();

                        goto case 2;
                    }
                case 2:
                    {
                        TourneyType = (TourneyType)reader.ReadEncodedInt();

                        goto case 1;
                    }
                case 1:
                    {
                        GroupType = (GroupingType)reader.ReadEncodedInt();
                        TieType = (TieType)reader.ReadEncodedInt();
                        SignupPeriod = reader.ReadTimeSpan();

                        goto case 0;
                    }
                case 0:
                    {
                        if (version < 3)
                        {
                            SuddenDeathRounds = 3;
                        }

                        m_ParticipantsPerMatch = reader.ReadEncodedInt();
                        m_PlayersPerParticipant = reader.ReadEncodedInt();
                        SignupPeriod = reader.ReadTimeSpan();
                        CurrentStage = TournamentStage.Inactive;
                        Pyramid = new TourneyPyramid();
                        Ruleset = new Ruleset(RulesetLayout.Root);
                        Ruleset.ApplyDefault(Ruleset.Layout.Defaults[0]);
                        Participants = new List<TourneyParticipant>();
                        Undefeated = new List<TourneyParticipant>();
                        Arenas = new List<Arena>();

                        break;
                    }
            }

            Timer.StartTimer(SliceInterval, SliceInterval, Slice);
        }

        public Tournament()
        {
            m_ParticipantsPerMatch = 2;
            m_PlayersPerParticipant = 1;
            Pyramid = new TourneyPyramid();
            Ruleset = new Ruleset(RulesetLayout.Root);
            Ruleset.ApplyDefault(Ruleset.Layout.Defaults[0]);
            Participants = new List<TourneyParticipant>();
            Undefeated = new List<TourneyParticipant>();
            Arenas = new List<Arena>();
            SignupPeriod = TimeSpan.FromMinutes(10.0);

            Timer.StartTimer(SliceInterval, SliceInterval, Slice);
        }

        public bool IsNotoRestricted => TourneyType != TourneyType.Standard;

        [CommandProperty(AccessLevel.GameMaster)]
        public EventController EventController { get; set; }

        [CommandProperty(AccessLevel.GameMaster)]
        public int SuddenDeathRounds { get; set; }

        [CommandProperty(AccessLevel.GameMaster)]
        public TourneyType TourneyType { get; set; }

        [CommandProperty(AccessLevel.GameMaster)]
        public GroupingType GroupType { get; set; }

        [CommandProperty(AccessLevel.GameMaster)]
        public TieType TieType { get; set; }

        [CommandProperty(AccessLevel.GameMaster)]
        public TimeSpan SuddenDeath { get; set; }

        public Ruleset Ruleset { get; set; }

        [CommandProperty(AccessLevel.GameMaster)]
        public int ParticipantsPerMatch
        {
            get => m_ParticipantsPerMatch;
            set => m_ParticipantsPerMatch = Math.Clamp(value, 2, 10);
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int PlayersPerParticipant
        {
            get => m_PlayersPerParticipant;
            set => m_PlayersPerParticipant = Math.Clamp(value, 1, 10);
        }

        [CommandProperty(AccessLevel.GameMaster)]
        public int LevelRequirement { get; set; }

        [CommandProperty(AccessLevel.GameMaster)]
        public bool FactionRestricted { get; set; }

        [CommandProperty(AccessLevel.GameMaster)]
        public TimeSpan SignupPeriod { get; set; }

        [CommandProperty(AccessLevel.GameMaster)]
        public DateTime SignupStart { get; set; }

        [CommandProperty(AccessLevel.GameMaster)]
        public TournamentStage CurrentStage { get; private set; }

        public TournamentStage Stage
        {
            get => CurrentStage;
            set => CurrentStage = value;
        }

        public TourneyPyramid Pyramid { get; set; }

        public List<Arena> Arenas { get; set; }

        public List<TourneyParticipant> Participants { get; set; }

        public List<TourneyParticipant> Undefeated { get; set; }

        public bool IsFactionRestricted => FactionRestricted || TourneyType == TourneyType.Faction;

        public bool HasParticipant(Mobile mob)
        {
            for (var i = 0; i < Participants.Count; ++i)
            {
                if (Participants[i].Players.Contains(mob))
                {
                    return true;
                }
            }

            return false;
        }

        public void Serialize(IGenericWriter writer)
        {
            writer.WriteEncodedInt(5); // version

            writer.Write(FactionRestricted);

            writer.Write(EventController);

            writer.WriteEncodedInt(SuddenDeathRounds);

            writer.WriteEncodedInt((int)TourneyType);

            writer.WriteEncodedInt((int)GroupType);
            writer.WriteEncodedInt((int)TieType);
            writer.Write(SuddenDeath);

            writer.WriteEncodedInt(m_ParticipantsPerMatch);
            writer.WriteEncodedInt(m_PlayersPerParticipant);
            writer.Write(SignupPeriod);
        }

        public void HandleTie(Arena arena, TourneyMatch match, List<TourneyParticipant> remaining)
        {
            if (remaining.Count == 1)
            {
                HandleWon(arena, match, remaining[0]);
            }

            if (remaining.Count < 2)
            {
                return;
            }

            var sb = new StringBuilder();

            sb.Append("The match has ended in a tie ");

            sb.Append(remaining.Count == 2 ? "between " : "among ");

            sb.Append(remaining.Count);

            sb.Append(remaining[0].Players.Count == 1 ? " players: " : " teams: ");

            var hasAppended = false;

            for (var j = 0; j < match.Participants.Count; ++j)
            {
                var part = match.Participants[j];

                if (remaining.Contains(part))
                {
                    if (hasAppended)
                    {
                        sb.Append(", ");
                    }

                    sb.Append(part.NameList);
                    hasAppended = true;
                }
                else
                {
                    Undefeated.Remove(part);
                }
            }

            sb.Append(". ");

            var whole = remaining.Count == 2 ? "both" : "all";

            var tieType = TieType;

            if (tieType == TieType.FullElimination && remaining.Count >= Undefeated.Count)
            {
                tieType = TieType.FullAdvancement;
            }

            switch (tieType)
            {
                case TieType.FullAdvancement:
                    {
                        sb.AppendFormat("In accordance with the rules, {0} parties are advanced.", whole);
                        break;
                    }
                case TieType.FullElimination:
                    {
                        for (var j = 0; j < remaining.Count; ++j)
                        {
                            Undefeated.Remove(remaining[j]);
                        }

                        sb.AppendFormat("In accordance with the rules, {0} parties are eliminated.", whole);
                        break;
                    }
                case TieType.Random:
                    {
                        var advanced = remaining.RandomElement();

                        for (var i = 0; i < remaining.Count; ++i)
                        {
                            if (remaining[i] != advanced)
                            {
                                Undefeated.Remove(remaining[i]);
                            }
                        }

                        if (advanced != null)
                        {
                            sb.AppendFormat(
                                "In accordance with the rules, {0} {1} advanced.",
                                advanced.NameList,
                                advanced.Players.Count == 1 ? "is" : "are"
                            );
                        }

                        break;
                    }
                case TieType.Highest:
                    {
                        TourneyParticipant advanced = null;

                        for (var i = 0; i < remaining.Count; ++i)
                        {
                            var part = remaining[i];

                            if (advanced == null || part.TotalLadderXP > advanced.TotalLadderXP)
                            {
                                advanced = part;
                            }
                        }

                        for (var i = 0; i < remaining.Count; ++i)
                        {
                            if (remaining[i] != advanced)
                            {
                                Undefeated.Remove(remaining[i]);
                            }
                        }

                        if (advanced != null)
                        {
                            sb.AppendFormat(
                                "In accordance with the rules, {0} {1} advanced.",
                                advanced.NameList,
                                advanced.Players.Count == 1 ? "is" : "are"
                            );
                        }

                        break;
                    }
                case TieType.Lowest:
                    {
                        TourneyParticipant advanced = null;

                        for (var i = 0; i < remaining.Count; ++i)
                        {
                            var part = remaining[i];

                            if (advanced == null || part.TotalLadderXP < advanced.TotalLadderXP)
                            {
                                advanced = part;
                            }
                        }

                        for (var i = 0; i < remaining.Count; ++i)
                        {
                            if (remaining[i] != advanced)
                            {
                                Undefeated.Remove(remaining[i]);
                            }
                        }

                        if (advanced != null)
                        {
                            sb.AppendFormat(
                                "In accordance with the rules, {0} {1} advanced.",
                                advanced.NameList,
                                advanced.Players.Count == 1 ? "is" : "are"
                            );
                        }

                        break;
                    }
            }

            Alert(arena, sb.ToString());
        }

        public void OnEliminated(DuelPlayer player)
        {
            var part = player.Participant;

            if (!part.Eliminated)
            {
                return;
            }

            if (TourneyType == TourneyType.FreeForAll)
            {
                var rem = 0;

                for (var i = 0; i < part.Context.Participants.Count; ++i)
                {
                    if (part.Context.Participants[i]?.Eliminated == false)
                    {
                        ++rem;
                    }
                }

                var tp = part.TourneyPart;

                if (tp == null)
                {
                    return;
                }

                if (rem == 1)
                {
                    GiveAwards(tp.Players, TrophyRank.Silver, ComputeCashAward() / 2);
                }
                else if (rem == 2)
                {
                    GiveAwards(tp.Players, TrophyRank.Bronze, ComputeCashAward() / 4);
                }
            }
        }

        public void HandleWon(Arena arena, TourneyMatch match, TourneyParticipant winner)
        {
            var sb = new StringBuilder();

            sb.Append("The match is complete. ");
            sb.Append(winner.NameList);

            if (winner.Players.Count > 1)
            {
                sb.Append(" have bested ");
            }
            else
            {
                sb.Append(" has bested ");
            }

            if (match.Participants.Count > 2)
            {
                sb.AppendFormat(
                    "{0} other {1}: ",
                    match.Participants.Count - 1,
                    winner.Players.Count == 1 ? "players" : "teams"
                );
            }

            var hasAppended = false;

            for (var j = 0; j < match.Participants.Count; ++j)
            {
                var part = match.Participants[j];

                if (part == winner)
                {
                    continue;
                }

                Undefeated.Remove(part);

                if (hasAppended)
                {
                    sb.Append(", ");
                }

                sb.Append(part.NameList);
                hasAppended = true;
            }

            sb.Append('.');

            if (TourneyType == TourneyType.Standard)
            {
                Alert(arena, sb.ToString());
            }
        }

        private int ComputeCashAward() => Participants.Count * m_PlayersPerParticipant * 2500;

        private void GiveAwards()
        {
            switch (TourneyType)
            {
                case TourneyType.FreeForAll:
                    {
                        if (Pyramid.Levels.Count < 1)
                        {
                            break;
                        }

                        var top = Pyramid.Levels[^1];

                        if (top.FreeAdvance != null || top.Matches.Count != 1)
                        {
                            break;
                        }

                        var match = top.Matches[0];
                        var winner = match.Winner;

                        if (winner != null)
                        {
                            GiveAwards(winner.Players, TrophyRank.Gold, ComputeCashAward());
                        }

                        break;
                    }
                case TourneyType.Standard:
                    {
                        if (Pyramid.Levels.Count < 2)
                        {
                            break;
                        }

                        var top = Pyramid.Levels[^1];

                        if (top.FreeAdvance != null || top.Matches.Count != 1)
                        {
                            break;
                        }

                        var cash = ComputeCashAward();

                        var match = top.Matches[0];
                        var winner = match.Winner;

                        for (var i = 0; i < match.Participants.Count; ++i)
                        {
                            var part = match.Participants[i];

                            if (part == winner)
                            {
                                GiveAwards(part.Players, TrophyRank.Gold, cash);
                            }
                            else
                            {
                                GiveAwards(part.Players, TrophyRank.Silver, cash / 2);
                            }
                        }

                        var next = Pyramid.Levels[^2];

                        if (next.Matches.Count > 2)
                        {
                            break;
                        }

                        for (var i = 0; i < next.Matches.Count; ++i)
                        {
                            match = next.Matches[i];
                            winner = match.Winner;

                            for (var j = 0; j < match.Participants.Count; ++j)
                            {
                                var part = match.Participants[j];

                                if (part != winner)
                                {
                                    GiveAwards(part.Players, TrophyRank.Bronze, cash / 4);
                                }
                            }
                        }

                        break;
                    }
            }
        }

        private void GiveAwards(List<Mobile> players, TrophyRank rank, int cash)
        {
            if (players.Count == 0)
            {
                return;
            }

            if (players.Count > 1)
            {
                cash /= players.Count - 1;
            }

            cash += 500;
            cash /= 1000;
            cash *= 1000;

            var sb = new StringBuilder();

            if (TourneyType == TourneyType.FreeForAll)
            {
                sb.Append(Participants.Count * m_PlayersPerParticipant);
                sb.Append("-man FFA");
            }
            else if (TourneyType == TourneyType.RandomTeam)
            {
                sb.Append(m_ParticipantsPerMatch);
                sb.Append("-Team");
            }
            else if (TourneyType == TourneyType.Faction)
            {
                sb.Append(m_ParticipantsPerMatch);
                sb.Append("-Team Faction");
            }
            else if (TourneyType == TourneyType.RedVsBlue)
            {
                sb.Append("Red v Blue");
            }
            else
            {
                for (var i = 0; i < m_ParticipantsPerMatch; ++i)
                {
                    if (sb.Length > 0)
                    {
                        sb.Append('v');
                    }

                    sb.Append(m_PlayersPerParticipant);
                }
            }

            if (EventController != null)
            {
                sb.Append(' ').Append(EventController.Title);
            }

            sb.Append(" Champion");

            var title = sb.ToString();

            for (var i = 0; i < players.Count; ++i)
            {
                var mob = players[i];

                if (mob?.Deleted != false)
                {
                    continue;
                }

                Item item = new Trophy(title, rank);

                if (!mob.PlaceInBackpack(item))
                {
                    mob.BankBox.DropItem(item);
                }

                if (cash > 0)
                {
                    item = new BankCheck(cash);

                    if (!mob.PlaceInBackpack(item))
                    {
                        mob.BankBox.DropItem(item);
                    }

                    mob.SendMessage(
                        "You have been awarded a {0} trophy and {1:N0}gp for your participation in this tournament.",
                        rank.ToString().ToLower(),
                        cash
                    );
                }
                else
                {
                    mob.SendMessage(
                        "You have been awarded a {0} trophy for your participation in this tournament.",
                        rank.ToString().ToLower()
                    );
                }
            }
        }

        public void Slice()
        {
            if (CurrentStage == TournamentStage.Signup)
            {
                var until = SignupStart + SignupPeriod - Core.Now;

                if (until <= TimeSpan.Zero)
                {
                    for (var i = Participants.Count - 1; i >= 0; --i)
                    {
                        var part = Participants[i];
                        var bad = false;

                        for (var j = 0; j < part.Players.Count; ++j)
                        {
                            var check = part.Players[j];

                            if (check.Deleted || check.Map == null || check.Map == Map.Internal || !check.Alive ||
                                Sigil.ExistsOn(check) || check.Region.IsPartOf<JailRegion>())
                            {
                                bad = true;
                                break;
                            }
                        }

                        if (bad)
                        {
                            for (var j = 0; j < part.Players.Count; ++j)
                            {
                                part.Players[j].SendMessage("You have been disqualified from the tournament.");
                            }

                            Participants.RemoveAt(i);
                        }
                    }

                    if (Participants.Count >= 2)
                    {
                        CurrentStage = TournamentStage.Fighting;

                        Undefeated.Clear();

                        Pyramid.Levels.Clear();
                        Pyramid.AddLevel(m_ParticipantsPerMatch, Participants, GroupType, TourneyType);

                        var level = Pyramid.Levels[0];

                        if (level.FreeAdvance != null)
                        {
                            Undefeated.Add(level.FreeAdvance);
                        }

                        for (var i = 0; i < level.Matches.Count; ++i)
                        {
                            var match = level.Matches[i];

                            Undefeated.AddRange(match.Participants);
                        }

                        Alert("Hear ye! Hear ye!", "The tournament will begin shortly.");
                    }
                    else
                    {
                        /*Alert( "Is this all?", "Pitiful. Signup extended." );
                        m_SignupStart = Core.Now;*/

                        Alert("Is this all?", "Pitiful. Tournament cancelled.");
                        CurrentStage = TournamentStage.Inactive;
                    }
                }
                else if (Math.Abs(until.TotalSeconds - TimeSpan.FromMinutes(1.0).TotalSeconds) <
                         SliceInterval.TotalSeconds / 2)
                {
                    Alert("Last call!", "If you wish to enter the tournament, sign up with the registrar now.");
                }
                else if (Math.Abs(until.TotalSeconds - TimeSpan.FromMinutes(5.0).TotalSeconds) <
                         SliceInterval.TotalSeconds / 2)
                {
                    Alert("The tournament will begin in 5 minutes.", "Sign up now before it's too late.");
                }
            }
            else if (CurrentStage == TournamentStage.Fighting)
            {
                if (Undefeated.Count == 1)
                {
                    var winner = Undefeated[0];

                    try
                    {
                        if (EventController != null)
                        {
                            Alert(
                                "The tournament has completed!",
                                $"Team {EventController.GetTeamName(Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner))} has won!"
                            );
                        }
                        else if (TourneyType == TourneyType.RandomTeam)
                        {
                            Alert(
                                "The tournament has completed!",
                                $"Team {Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) + 1} has won!"
                            );
                        }
                        else if (TourneyType == TourneyType.Faction)
                        {
                            if (m_ParticipantsPerMatch == 4)
                            {
                                var name = Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) switch
                                {
                                    0 => "Minax",
                                    1 => "Council of Mages",
                                    2 => "True Britannians",
                                    3 => "Shadowlords",
                                    _ => "(null)"
                                };

                                Alert("The tournament has completed!", $"The {name} team has won!");
                            }
                            else if (m_ParticipantsPerMatch == 2)
                            {
                                Alert(
                                    "The tournament has completed!",
                                    $"The {(Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) == 0 ? "Evil" : "Hero")} team has won!"
                                );
                            }
                            else
                            {
                                Alert(
                                    "The tournament has completed!",
                                    $"Team {Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) + 1} has won!"
                                );
                            }
                        }
                        else if (TourneyType == TourneyType.RedVsBlue)
                        {
                            Alert(
                                "The tournament has completed!",
                                $"Team {(Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) == 0 ? "Red" : "Blue")} has won!"
                            );
                        }
                        else
                        {
                            Alert(
                                "The tournament has completed!",
                                $"{winner.NameList} {(winner.Players.Count > 1 ? "are" : "is")} the champion{(winner.Players.Count == 1 ? "" : "s")}."
                            );
                        }
                    }
                    catch
                    {
                        // ignored
                    }

                    GiveAwards();

                    CurrentStage = TournamentStage.Inactive;
                    Undefeated.Clear();
                }
                else if (Pyramid.Levels.Count > 0)
                {
                    var activeLevel = Pyramid.Levels[^1];
                    var stillGoing = false;

                    for (var i = 0; i < activeLevel.Matches.Count; ++i)
                    {
                        var match = activeLevel.Matches[i];

                        if (match.Winner == null)
                        {
                            stillGoing = true;

                            if (!match.InProgress)
                            {
                                for (var j = 0; j < Arenas.Count; ++j)
                                {
                                    var arena = Arenas[j];

                                    if (!arena.IsOccupied)
                                    {
                                        match.Start(arena, this);
                                        break;
                                    }
                                }
                            }
                        }
                    }

                    if (!stillGoing)
                    {
                        for (var i = Undefeated.Count - 1; i >= 0; --i)
                        {
                            var part = Undefeated[i];
                            var bad = false;

                            for (var j = 0; j < part.Players.Count; ++j)
                            {
                                var check = part.Players[j];

                                if (check.Deleted || check.Map == null || check.Map == Map.Internal || !check.Alive ||
                                    Sigil.ExistsOn(check) || check.Region.IsPartOf<JailRegion>())
                                {
                                    bad = true;
                                    break;
                                }
                            }

                            if (!bad)
                            {
                                continue;
                            }

                            for (var j = 0; j < part.Players.Count; ++j)
                            {
                                part.Players[j].SendMessage("You have been disqualified from the tournament.");
                            }

                            Undefeated.RemoveAt(i);

                            if (Undefeated.Count == 1)
                            {
                                var winner = Undefeated[0];

                                try
                                {
                                    if (EventController != null)
                                    {
                                        Alert(
                                            "The tournament has completed!",
                                            $"Team {EventController.GetTeamName(Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner))} has won"
                                        );
                                    }
                                    else if (TourneyType == TourneyType.RandomTeam)
                                    {
                                        Alert(
                                            "The tournament has completed!",
                                            $"Team {Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) + 1} has won!"
                                        );
                                    }
                                    else if (TourneyType == TourneyType.Faction)
                                    {
                                        if (m_ParticipantsPerMatch == 4)
                                        {
                                            var name = Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) switch
                                            {
                                                0 => "Minax",
                                                1 => "Council of Mages",
                                                2 => "True Britannians",
                                                3 => "Shadowlords",
                                                _ => "(null)"
                                            };

                                            Alert("The tournament has completed!", $"The {name} team has won!");
                                        }
                                        else if (m_ParticipantsPerMatch == 2)
                                        {
                                            Alert(
                                                "The tournament has completed!",
                                                $"The {(Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) == 0 ? "Evil" : "Hero")} team has won!"
                                            );
                                        }
                                        else
                                        {
                                            Alert(
                                                "The tournament has completed!",
                                                $"Team {Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) + 1} has won!"
                                            );
                                        }
                                    }
                                    else if (TourneyType == TourneyType.RedVsBlue)
                                    {
                                        Alert(
                                            "The tournament has completed!",
                                            $"Team {(Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) == 0 ? "Red" : "Blue")} has won!"
                                        );
                                    }
                                    else
                                    {
                                        Alert(
                                            "The tournament has completed!",
                                            $"{winner.NameList} {(winner.Players.Count > 1 ? "are" : "is")} the champion{(winner.Players.Count == 1 ? "" : "s")}."
                                        );
                                    }
                                }
                                catch
                                {
                                    // ignored
                                }

                                GiveAwards();

                                CurrentStage = TournamentStage.Inactive;
                                Undefeated.Clear();
                                break;
                            }
                        }

                        if (Undefeated.Count > 1)
                        {
                            Pyramid.AddLevel(m_ParticipantsPerMatch, Undefeated, GroupType, TourneyType);
                        }
                    }
                }
            }
        }

        public void Alert(params string[] alerts)
        {
            for (var i = 0; i < Arenas.Count; ++i)
            {
                Alert(Arenas[i], alerts);
            }
        }

        public void Alert(Arena arena, params string[] alerts)
        {
            if (arena?.Announcer == null)
            {
                return;
            }

            var count = 0;

            Timer.StartTimer(TimeSpan.FromSeconds(0.5), alerts.Length,
                () =>
                {
                    arena.Announcer.PublicOverheadMessage(MessageType.Regular, 0x35, false, alerts[count++]);
                }
            );
        }
    }
}
