Contains information for the GetConditions event. The event handler should fill Conditions with search conditions.
Inheritance: System.EventArgs
        /// <summary>
        /// Selects which video will be played next.
        /// </summary>
        /// <param name="queuePos">The video position to select. 0 for current, 1 for next.</param>
        /// <param name="maintainCurrent">True to keep the next video and only select alternate options, false to change next video.</param>
        /// <param name="attempts">The number of attemps already made, to avoid infinite loop.</param>
        /// <returns>Whether the file is downloading.</returns>
        private async Task <bool> SelectNextVideoAsync(int queuePos, bool maintainCurrent, int attempts)
        {
            bool IsDownloading = false;

            if (attempts > 3)
            {
                nextVideo = null;
                return(false);
            }

            timerChangeConditions.Stop();

            // Get video conditions
            GetConditionsEventArgs e = new GetConditionsEventArgs(FilterSettings);

            e.QueuePos = queuePos;
            Application.Current.Dispatcher.Invoke(() => GetConditions?.Invoke(this, e));

            // Select random video matching conditions.
            List <Media> Result = PlayerAccess.SelectVideo(FilterSettings.Update(playedVideos, Settings.SavedFile.AutoDownload), 3, maintainCurrent ? nextVideo : null);

            lastSearchResultCount = FilterSettings.TotalFound;

            // If no video is found, try again while increasing tolerance
            if (Result == null)
            {
                e = new GetConditionsEventArgs(FilterSettings);
                e.IncreaseTolerance = true;
                Application.Current.Dispatcher.Invoke(() => GetConditions?.Invoke(this, e));
                Result = PlayerAccess.SelectVideo(FilterSettings.Update(null, Settings.SavedFile.AutoDownload), 3, maintainCurrent ? nextVideo : null);
                FilterSettings.TotalFound = lastSearchResultCount;
            }

            if (Result != null)
            {
                if (nextVideo != null)
                {
                    CancelNextDownload(nextVideo);
                }
                NextVideoOptions = new ObservableCollection <Media>(Result);
                nextVideo        = Result.FirstOrDefault();
                IsDownloading    = await PrepareNextVideoAsync(queuePos, attempts).ConfigureAwait(false);
            }

            timerChangeConditions.Stop();
            Application.Current.Dispatcher.Invoke(() => PlaylistChanged?.Invoke(this, new EventArgs()));

            return(IsDownloading);
        }
        public async Task EnsureNextVideoMatchesConditionsAsync(bool skipping) {
            int QueuePos = skipping ? 0 : 1;
            if (nextVideo != null && PlayMode == PlayerMode.Normal) {
                // Get new conditions
                GetConditionsEventArgs Args = new GetConditionsEventArgs(FilterSettings);
                Args.QueuePos = QueuePos;
                if (GetConditions != null)
                    GetConditions(this, Args);

                // Run the conditions on the next video in the playlist
                if (!PlayerAccess.VideoMatchesConditions(nextVideo, FilterSettings.Update(playedVideos, Settings.SavedFile.AutoDownload))) {
                    // If next video doesn't match conditions, select another one
                    await SelectNextVideoAsync(QueuePos);
                }
            } else if (nextVideo == null)
                await SelectNextVideoAsync(QueuePos);
        }
        private async void business_GetConditions(object sender, GetConditionsEventArgs e) {
            var Filters = e.Conditions.RatingFilters;
            Filters.Clear();
            switch (SessionCore.Instance.Business.PlayMode) {
                case PlayerMode.Normal:
                    double MaxCond = IntensitySlider.Value + e.QueuePos * GrowthSlider.Value;
                    // If decreasing heat, go down to Water from 1 above minimum
                    if (GrowthSlider.Value < 0 && MaxCond < IntensitySlider.Minimum + 1)
                        MaxCond = IntensitySlider.Minimum;
                    if (MaxCond > IntensitySlider.Maximum)
                        MaxCond = IntensitySlider.Maximum;
                    if (MaxCond > IntensitySlider.Minimum) {
                        // Exclude videos with Water >= 6
                        Filters.AddRange(FilterPresets.PresetWater(true));
                        // Exclude videos with Fire >= 8.5 && Intensity >= 9.5 unless we're at maximum heat.
                        if (MaxCond < IntensitySlider.Maximum)
                            Filters.AddRange(FilterPresets.PresetFire(true));

                        if (PolarityFocus.Text == "Intensity")
                            MaxCond -= 1;
                        // Min/Max Values.
                        SearchRatingSetting MinFilter = new SearchRatingSetting(PolarityFocus.Text, OperatorConditionEnum.GreaterOrEqual, Math.Round(MaxCond - ToleranceSlider.Value, 1));
                        SearchRatingSetting MaxFilter = new SearchRatingSetting(PolarityFocus.Text, OperatorConditionEnum.Smaller, Math.Round(MaxCond, 1));
                        Filters.Add(MinFilter);
                        Filters.Add(MaxFilter);
                        if (PolarityFocus.Text == "Intensity" && MaxCond == IntensitySlider.Maximum - 1)
                            MaxFilter.Value = IntensitySlider.Maximum;
                        if (e.IncreaseTolerance) {
                            MinFilter.Value -= .5f;
                            MaxFilter.Value += .5f;
                        }
                        if (PolarityFocus.Text == "Physical" || PolarityFocus.Text == "Emotional" || PolarityFocus.Text == "Spiritual") {
                            // Don't get videos that are more than .5 stronger on other values.
                            Filters.Add(new SearchRatingSetting("!" + PolarityFocus.Text, OperatorConditionEnum.Smaller, MaxFilter.Value + .5f));
                        } else if (PolarityFocus.Text == "Intensity") {
                            Filters.Add(new SearchRatingSetting("!Intensity", OperatorConditionEnum.Smaller, MaxFilter.Value + 2f));
                        }
                    } else { // Water
                        IntensitySlider.Value = IntensitySlider.Minimum;
                        await SessionCore.Instance.Business.SetWaterVideosAsync(true);
                    }
                    // Change condition display after "Fire" returns to normal.
                    DisplayConditionsText();
                    break;
                case PlayerMode.WarmPause:
                case PlayerMode.Fire:
                    Filters.AddRange(FilterPresets.PresetPause());
                    break;
                case PlayerMode.Water:
                    if (!e.IncreaseTolerance) {
                        Filters.Add(new SearchRatingSetting("Water", OperatorConditionEnum.GreaterOrEqual, 4f));
                    } else {
                        Filters.Add(new SearchRatingSetting("Intensity", OperatorConditionEnum.Smaller, 7f));
                        Filters.Add(new SearchRatingSetting("Party", OperatorConditionEnum.Smaller, 2f));
                        Filters.Add(new SearchRatingSetting("Vitality", OperatorConditionEnum.Smaller, 2f));
                        Filters.Add(new SearchRatingSetting("Fire", OperatorConditionEnum.Smaller, 2f));
                        Filters.Add(new SearchRatingSetting("!", OperatorConditionEnum.Smaller, 9f));
                    }
                    break;
                case PlayerMode.RequestCategory:
                    // Filters are already defined in Business.FilterSettings.
                    Filters.Add(new SearchRatingSetting());
                    break;
            }
        }
        /// <summary>
        /// Selects which video will be played next.
        /// </summary>
        /// <param name="queuePos">The video position to select. 0 for current, 1 for next.</param>
        /// <param name="attempts">The number of attemps already made, to avoid infinite loop.</param>
        /// <returns>Whether the file is downloading.</returns>
        private async Task<bool> SelectNextVideoAsync(int queuePos, int attempts) {
            bool IsDownloading = false;
            if (attempts > 3) {
                nextVideo = null;
                return false;
            }

            timerChangeConditions.Stop();

            // Get video conditions
            GetConditionsEventArgs e = new GetConditionsEventArgs(FilterSettings);
            e.QueuePos = queuePos;
            if (GetConditions != null)
                GetConditions(this, e);

            // Select random video matching conditions.
            Media Result = PlayerAccess.SelectVideo(FilterSettings.Update(playedVideos, Settings.SavedFile.AutoDownload));
            lastSearchResultCount = FilterSettings.TotalFound;

            // If no video is found, try again while increasing tolerance
            if (Result == null) {
                e = new GetConditionsEventArgs(FilterSettings);
                e.IncreaseTolerance = true;
                if (GetConditions != null)
                    GetConditions(this, e);
                Result = PlayerAccess.SelectVideo(FilterSettings.Update(null, Settings.SavedFile.AutoDownload));
                FilterSettings.TotalFound = lastSearchResultCount;
            }

            if (Result != null) {
                if (nextVideo != null)
                    CancelNextDownload(nextVideo);
                nextVideo = Result;
                IsDownloading = await PrepareNextVideoAsync(queuePos, attempts);
            }

            timerChangeConditions.Stop();
            if (PlaylistChanged != null)
                PlaylistChanged(this, new EventArgs());

            return IsDownloading;
        }
        /// <summary>
        /// Selects which video will be played next.
        /// </summary>
        /// <param name="queuePos">The video position to select. 0 for current, 1 for next.</param>
        /// <param name="maintainCurrent">True to keep the next video and only select alternate options, false to change next video.</param>
        /// <param name="attempts">The number of attemps already made, to avoid infinite loop.</param>
        /// <returns>Whether the file is downloading.</returns>
        private async Task<bool> SelectNextVideoAsync(int queuePos, bool maintainCurrent, int attempts) {
            bool IsDownloading = false;
            if (attempts > 3) {
                nextVideo = null;
                return false;
            }

            timerChangeConditions.Stop();

            // Get video conditions
            GetConditionsEventArgs e = new GetConditionsEventArgs(FilterSettings);
            e.QueuePos = queuePos;
            Application.Current.Dispatcher.Invoke(() => GetConditions?.Invoke(this, e));

            // Select random video matching conditions.
            List<Media> Result = PlayerAccess.SelectVideo(FilterSettings.Update(playedVideos, Settings.SavedFile.AutoDownload), 3, maintainCurrent ? nextVideo : null);
            lastSearchResultCount = FilterSettings.TotalFound;

            // If no video is found, try again while increasing tolerance
            if (Result == null) {
                e = new GetConditionsEventArgs(FilterSettings);
                e.IncreaseTolerance = true;
                Application.Current.Dispatcher.Invoke(() => GetConditions?.Invoke(this, e));
                Result = PlayerAccess.SelectVideo(FilterSettings.Update(null, Settings.SavedFile.AutoDownload), 3, maintainCurrent ? nextVideo : null);
                FilterSettings.TotalFound = lastSearchResultCount;
            }

            if (Result != null) {
                if (nextVideo != null)
                    CancelNextDownload(nextVideo);
                NextVideoOptions = new ObservableCollection<Media>(Result);
                nextVideo = Result.FirstOrDefault();
                IsDownloading = await PrepareNextVideoAsync(queuePos, attempts).ConfigureAwait(false);
            }

            timerChangeConditions.Stop();
            Application.Current.Dispatcher.Invoke(() => PlaylistChanged?.Invoke(this, new EventArgs()));

            return IsDownloading;
        }