public void Clear()
 {
     currentNotified = false;
     currentFinishedNormally = false;
     currentBattle = null;
     CurrentBattleApi.Clear();
 }
        public MapNotification(Battle battle, double timeLeft, int startHeight, int mapDesiredWidth, bool mapLoaded, BattleNotificationSettings settings)
            : base(settings, battle.Duration)
        {
            InitializeComponent();
            this.battle = battle;

            InitializeBattleTimer(timeLeft);
            InitializePicture(mapDesiredWidth);
            SetupDialogLocation(settings.Basic.DisplayScreen, startHeight);

            this.mapLoaded = mapLoaded;
            SetupTextOverMap(battle, timeLeft, settings.Map);
        }
        public BattleNotification(Battle battle, double timeLeft, int startHeight, BattleNotificationSettings settings)
            : base(settings, battle.Duration)
        {
            InitializeComponent();

            InitializeBattleTimer(timeLeft);
            SetupDialogLocation(settings.Basic.DisplayScreen, startHeight);

            SetupControls(battle);

            if (settings.General.TransparentStyle)
                SetupOutlineLabels();

            if (settings.General.HidePrintMap)
            {
                PrintMapButton.Visible = false;
                MapCheckBox.Location = new Point(PrintMapButton.Location.X - (MapCheckBox.Width - PrintMapButton.Width), MapCheckBox.Location.Y);
            }
        }
        private void SetupTextOverMap(Battle battle, double timeLeft, MapSettings settings)
        {
            Color color = settings.TextMapColor;
            Locate locate = new Locate(PictureBox.Width, PictureBox.Height);

            if (settings.ShowLifeSeconds)
            {
                TimerLabel.ForeColor = color;
                TimerLabel.Parent = PictureBox;
                TimerLabel.Visible = true;
                locate.BottomCenter(TimerLabel, 20);
            }

            if (settings.ShowLevelName || settings.ShowDesigner)
            {
                HeaderLabel.ForeColor = color;
                HeaderLabel.Parent = PictureBox;
                HeaderLabel.Visible = true;
                StringBuilder text = new StringBuilder();
                if (settings.ShowLevelName)
                    text.Append(battle.Name);
                if (settings.ShowDesigner)
                    text.Append(" by " + battle.Desginer);
                HeaderLabel.Text = text.ToString();
                HeaderLabel.MaximumSize = new Size(PictureBox.Width, PictureBox.Height);
                locate.BottomRight(HeaderLabel, 5);
            }

            if (settings.ShowType)
            {
                TypeLabel.ForeColor = color;
                TypeLabel.Parent = PictureBox;
                TypeLabel.Visible = true;
                TypeLabel.Text = EnumExtensions.GetDescription(battle.Type);
                locate.BottomLeft(TypeLabel, 5);
            }

            if (settings.ShowAttributes)
            {
                AttributesLabel.ForeColor = color;
                AttributesLabel.Parent = PictureBox;
                AttributesLabel.Visible = true;
                List<string> attributes = new List<string>();
                foreach (BattleAttribute att in EnumExtensions.GetFlags(battle.Attributes))
                    attributes.Add(EnumExtensions.GetDescription(att));

                AttributesLabel.Text = Util.FirstCharToUpper(string.Join(", ", attributes).ToLower());
                AttributesLabel.MaximumSize = new Size(PictureBox.Width, PictureBox.Height);
                int margin = AttributesLabel.Height + 2;
                locate.BottomCenter(AttributesLabel, 20);
                locate.MoveUp(TimerLabel, margin);
            }

            // Check for collisions.
            if ((settings.ShowDesigner || settings.ShowLevelName) && settings.ShowType
                && HeaderLabel.Width > PictureBox.Width - TypeLabel.Width - 10)
            {
                locate.ToLeft(HeaderLabel, 5);
                locate.MoveUp(TypeLabel, HeaderLabel.Height + 2);
                locate.MoveUp(TimerLabel, HeaderLabel.Height + 2);
                if (settings.ShowAttributes)
                {
                    locate.BottomRight(AttributesLabel, 5);
                    locate.MoveUp(AttributesLabel, HeaderLabel.Height + 2);
                    locate.BottomRight(TimerLabel, 5);
                    locate.MoveUp(TimerLabel, AttributesLabel.Height + HeaderLabel.Height + TypeLabel.Height + 2 );
                    if (AttributesLabel.Width > PictureBox.Width - TypeLabel.Width - 10)
                    {
                        locate.ToLeft(AttributesLabel, 5);
                        locate.MoveUp(TypeLabel, AttributesLabel.Height + 2);
                    }
                }
                else if (settings.ShowLifeSeconds && TimerLabel.Location.Y + TimerLabel.Height > HeaderLabel.Location.Y)
                {
                    // Timer is over Header, take out designer to fit everything.
                    if (!showOnlyTimerAndType)
                    {
                        showOnlyTimerAndType = true;
                        HeaderLabel.Visible = false;
                        settings.ShowDesigner = false;
                        tooSmallMap = true;
                        SetupTextOverMap(battle, timeLeft, settings);
                    }
                }
            }

            // Check if important information is not shown.
            if (settings.ShowLifeSeconds)
            {
                if (TimerLabel.Location.Y < 0)
                {
                    if (!tooSmallMap)
                    {
                        tooSmallMap = true;
                        AttributesLabel.Visible = false;
                        settings.ShowAttributes = false;
                        SetupTextOverMap(battle, timeLeft, settings);
                    }
                    else
                    {
                        HeaderLabel.Visible = false;
                        locate.BottomRight(TimerLabel, 5);
                        if (settings.ShowType)
                            locate.BottomLeft(TypeLabel, 5);
                    }
                }
            }
        }
        public void ShowBattleNotification(IMain m, Battle battle, bool showCurrent = false, bool simulation = false)
        {
            ClearBattleNotification();

            BattleNotificationSettings settings = UserSettings.Instance.GetBattleNotificationSettings();

            if (settings.Basic.ShowBattleDialog || settings.Basic.ShowMapDialog)
            {
                bool mapOK = SetMap(battle, showCurrent, simulation);

                double timeLeft = battle.TimeLeft;
                if (settings.Basic.ShowBattleDialog)
                    bn = new BattleNotification(battle, timeLeft, 0, settings);

                int height = bn == null ? 0 : bn.Height + 20;
                mn = new MapNotification(battle, timeLeft, height, MapSizeIndexToWidth(settings.Basic.MapSize), mapOK, settings);
            }

            SetupWindowsDisplayBehaviour(settings);

            if (settings.Basic.ShowMapDialog)
                m.ShowNotification(mn);
            if (settings.Basic.ShowBattleDialog)
                m.ShowNotification(bn);

            SetupSound(settings);
            SetupLifeTime(settings);
        }
        private bool SetMap(Battle battle, bool showCurrent, bool simulation)
        {
            try
            {
                if (battle.Type.HasFlag(BattleType.OneHourTT) && !simulation)
                    Map = Properties.Resources.OneHourTTMap;
                else if (!showCurrent || downloadCurrentMap || Map == null || !battle.MapId.Equals(lastLoadedMapId))
                {
                    downloadCurrentMap = false;
                    lastLoadedMapId = battle.MapId;
                    Map = WebRequestHelper.GetImageFromUrl(battle.MapUrl + "/600");
                }
            }
            catch (Exception ex)
            {
                if (!simulation)
                {
                    Logger.Log(200, ex);
                    return false;
                }
                else
                    downloadCurrentMap = true;
                Map = Properties.Resources.about;
            }

            return true;
        }
        public void SimulateNewBattle()
        {
            Random random = new Random();
            int id = random.Next(0, 92350);
            int duration = random.Next(1, 61);
            int attributes = random.Next(1, 2048);
            int type = random.Next(0, 11);
            Battle battle = new Battle()
            {
                FileName = "Battle Notifier.lev",
                MapUrl = null,
                Duration = duration,
                Attributes = (BattleAttribute)attributes,
                Type = (BattleType)type,
                StartedDateTime = DateTime.Now,
                Desginer = "Pab",
                Id = id
            };

            ShowBattleNotification(BattleNotifierController.Instance.MainView, battle, false, true);
        }
        private void SetBattleUrls(Battle battle)
        {
            HtmlAgilityPack.HtmlDocument document = new HtmlWeb().Load(battle.Url);

            battle.LevelUrl = document.DocumentNode.Descendants("a")
                                                .Select(e => e.GetAttributeValue("href", null))
                                                .Where(s => !String.IsNullOrEmpty(s) && s.StartsWith(Settings.Default.EOLLevelUrl))
                                                .FirstOrDefault();

            battle.MapUrl = document.DocumentNode.Descendants("img")
                                            .Select(e => e.GetAttributeValue("src", null))
                                            .Where(s => !String.IsNullOrEmpty(s) && s.StartsWith(Settings.Default.EOLMapsUrl))
                                            .FirstOrDefault();
        }
        /// <summary>
        /// Notificate current battle if any, and return a new interval for the next notification.
        /// </summary>
        /// <returns> Next notification interval in seconds. </returns>
        private double NotifyBattle()
        {
            double nextUpdate = 5; // Seconds.

            Battle battle = GetOngoingBattleIfAny();

            if (battle == null || currentFinishedNormally)
            {
                if (currentFinishedNormally)
                    nextUpdate = 115;
                else
                    nextUpdate = 5;
                currentBattle = null;
                currentFinishedNormally = false;
                currentNotified = false;
            }
            else // Ongoing battle.
            {
                double timePassed = (CurrentDateTime - battle.StartedDateTime).TotalSeconds;
                double timeLeft = (battle.Duration * 60) - timePassed;

                // New battle.
                if (!battle.Equals(currentBattle))
                {
                    currentBattle = battle;
                }

                // Notificate battle.
                if (!currentNotified)
                {
                    NotificationsController.Instance.CurrentBattle = currentBattle;
                    if (FilterBattle(currentBattle))
                    {
                        currentNotified = true;
                        NotificationsController.Instance.ShowBattleNotification(MainView, currentBattle);
                    }
                }

                if (timeLeft < 1)
                {
                    nextUpdate = 1;
                    currentFinishedNormally = true;
                }
                else if (timePassed < 60) // Started recently.
                    nextUpdate = 20;
                else if (currentBattle.Duration < 10)
                {
                    // Short battle.
                    nextUpdate = timeLeft;
                    currentFinishedNormally = true;
                }
                else
                {
                    if (timeLeft <= currentBattle.Duration * 60 * 0.20)
                    {
                        // Short time left proportional to duration.
                        nextUpdate = timeLeft;
                        currentFinishedNormally = true;
                    }
                    else
                        nextUpdate = currentBattle.Duration * 60 * 0.20;
                }
            }

            return nextUpdate;
        }
        /// <summary>
        /// Get the current battle from domi's api, and elmaonline.
        /// </summary>
        /// <returns> Ongoing battle if any, else null.</returns>
        private Battle GetOngoingBattleIfAny()
        {
            try
            {
                XmlDocument xmlDoc = WebRequestHelper.GetXmlFromUrl(Settings.Default.CurrentBattleApiUrl);

                CurrentDateTime = DateTime.Now;
                if (xmlDoc.FirstChild.HasChildNodes)
                {
                    Battle battle = new Battle();

                    battle.Desginer = xmlDoc.DocumentElement.SelectSingleNode("designer").InnerText;
                    battle.FileName = xmlDoc.DocumentElement.SelectSingleNode("file_name").InnerText;

                    int startDelta = 0;
                    string strDelta = xmlDoc.DocumentElement.SelectSingleNode("start_delta").InnerText;
                    if (!Int32.TryParse(strDelta, out startDelta))
                    {
                        double delta = double.Parse(strDelta, System.Globalization.CultureInfo.InvariantCulture);
                        startDelta = Convert.ToInt32(delta);
                    }

                    battle.StartedDateTime = CurrentDateTime.AddSeconds(Convert.ToInt32(startDelta));

                    battle.Type = (BattleType)Convert.ToInt32(xmlDoc.DocumentElement.SelectSingleNode("battle_type").InnerText);
                    battle.Attributes = (BattleAttribute)Convert.ToInt32(xmlDoc.DocumentElement.SelectSingleNode("battle_attrs").InnerText);
                    battle.Duration = Convert.ToInt32(xmlDoc.DocumentElement.SelectSingleNode("duration").InnerText) / 60;

                    battle.Id = Convert.ToInt32(xmlDoc.DocumentElement.SelectSingleNode("id").InnerText);

                    if (!eolDataLoaded)
                    {
                        try
                        {
                            SetBattleUrls(battle);

                            eolDataLoaded = true;
                        }
                        catch (Exception ex)
                        {
                            try
                            {
                                SetBattleUrls(battle);
                                Logger.Log(101, ex);
                            }
                            catch (Exception iex)
                            {
                                Logger.Log(103, iex);
                            }
                        }
                    }

                    return battle;
                }
                else
                {
                    eolDataLoaded = false;
                    return null;
                }
            }
            catch (Exception ex)
            {
                Logger.Log(100, ex);
                return null;
            }
        }
        private bool FilterDesigners(Battle battle)
        {
            foreach (string designer in MainPanel.CheckedBlackList)
                if (designer.Equals(battle.Desginer, StringComparison.InvariantCultureIgnoreCase))
                    return false;

            if (MainPanel.HasAllDesignersChecked())
                return true;

            foreach (string designer in MainPanel.CheckedDesigners)
                if (designer.Equals(battle.Desginer, StringComparison.InvariantCultureIgnoreCase))
                    return true;

            return false;
        }
        private bool FilterBattleTypes(Battle battle)
        {
            if (MainPanel.HasAllBattleTypesChecked())
                return true;

            foreach (string type in MainPanel.CheckedBattleTypes)
            {
                if (type.Equals(EnumExtensions.GetDescription(battle.Type)))
                    return true;
            }

            return false;
        }
 /// <summary>
 /// Use user preferences to filter wanted battles.
 /// </summary>
 /// <param name="battle"> Battle to filter. </param>
 /// <returns> True if the battle fullfils the user preferences, else false.</returns>
 private bool FilterBattle(Battle battle)
 {
     return FilterBattleTypes(battle) && FilterDesigners(battle);
 }
        /// <summary>
        /// Stop notifying battles.
        /// </summary>
        public void StopNotifying()
        {
            // Stop notifying battles.
            notificationTimer.Stop();
            IsNotifyingBattle = false;

            // Reset all helpers.
            currentNotified = false;
            currentFinishedNormally = false;
            currentBattle = null;
            eolDataLoaded = false;
        }
        private void SetupControls(Battle battle)
        {
            HeadlineLinkLabel.Text = battle.Name + " by " + battle.Desginer;
            if (HeadlineLinkLabel.Width + HeadlineLinkLabel.Location.X > this.Width - HeadlineLinkLabel.Location.X * 2)
                HeadlineLinkLabel.Text = HeadlineLinkLabel.Text.Substring(0, 24) + "...";
            LinkLabel.Link battleLink = new LinkLabel.Link();
            battleLink.LinkData = battle.Url;
            HeadlineLinkLabel.Links.Add(battleLink);

            BattleTypeLabel.Text = EnumExtensions.GetDescription(battle.Type) + " battle";

            List<string> attributes = new List<string>();
            foreach (BattleAttribute att in EnumExtensions.GetFlags(battle.Attributes))
            {
                attributes.Add(EnumExtensions.GetDescription(att));
            }
            fullAttributesText = Util.FirstCharToUpper(string.Join(", ", attributes).ToLower());
            if (fullAttributesText.Length > maxAttributesLength)
                AttributesLabel.Text = fullAttributesText.Substring(0, maxAttributesLength) + "...";
            else
                AttributesLabel.Text = fullAttributesText;

            DurationLabel.Text = battle.Duration + " mins";
        }
        /// <summary>
        /// Notificate current battle if any, and return a new interval for the next notification.
        /// </summary>
        /// <returns> Next notification interval in seconds. </returns>
        public double NotifyBattle()
        {
            double nextUpdate = 5; // Seconds.

            Battle battle = CurrentBattleApi.GetOngoingBattleIfAny();

            if (battle == null || currentFinishedNormally)
            {
                if (currentFinishedNormally)
                    nextUpdate = 115;
                else
                    nextUpdate = 5;
                currentBattle = null;
                currentFinishedNormally = false;
                currentNotified = false;
            }
            else // Ongoing battle.
            {
                // New battle.
                if (!battle.Equals(currentBattle))
                    currentBattle = battle;

                // Notificate battle.
                if (!currentNotified)
                {
                    NotificationsController.Instance.CurrentBattle = currentBattle;
                    if (FilterBattle(currentBattle))
                    {
                        currentNotified = true;
                        NotificationsController.Instance.ShowBattleNotification(MainView, currentBattle);
                    }
                }

                double timePassed = battle.TimePassed;
                double timeLeft = (battle.Duration * 60) - timePassed;

                if (timeLeft < 1)
                {
                    nextUpdate = 1;
                    currentFinishedNormally = true;
                }
                else if (timePassed < 60 || battle.Type.HasFlag(BattleType.OneLife)) // Started recently or OneLife.
                    nextUpdate = 20;
                else if (currentBattle.Duration < 10)
                {
                    // Short battle.
                    nextUpdate = timeLeft;
                    currentFinishedNormally = true;
                }
                else
                {
                    if (timeLeft <= currentBattle.Duration * 60 * 0.20)
                    {
                        // Short time left proportional to duration.
                        nextUpdate = timeLeft;
                        currentFinishedNormally = true;
                    }
                    else
                        nextUpdate = currentBattle.Duration * 60 * 0.20;
                }
            }

            return nextUpdate;
        }