public static AudioFileSearchCollection GetBestSearchCollection(AudioLibrary audioLibrary, AODLoadSheetRow lsr)
        {
            if (lsr.OriginalSearchStrategy != lsr.Tokens.SearchStrategy)
            {
                lsr.Tokens.SetOriginalSearchStrategy();
            }

            AudioFileSearchCollection collection_1      = GetSearchCollection(audioLibrary, lsr); //SearchStrategyType defined by loadsheet (Original Search Strategy)
            AudioFileOption           candidateOption_1 = collection_1.BestOption;

            if (collection_1.IsOptionQuickSearchElligible(candidateOption_1, SearchMethodType.Both, Globals.AccurateThreshold))  //[Prefered result]  Accurate scoring and not too many options in final pool (skip alternative strategy search for performance)
            {
                return(collection_1);
            }

            if (lsr.Tokens.SearchStrategy == SearchStrategyType.CD)
            {
                lsr.Tokens.ConfigureSearchStrategy_OTHER(true);
            }
            else if (lsr.Tokens.SearchStrategy == SearchStrategyType.OTHER)
            {
                lsr.Tokens.ConfigureSearchStrategy_CD(true);
            }

            AudioFileSearchCollection collection_2      = GetSearchCollection(audioLibrary, lsr); //Alternative SearchStrategyType if needed
            AudioFileOption           candidateOption_2 = collection_2.BestOption;

            SuggestedAudioFile suggestedOption_1 = new SuggestedAudioFile(collection_1);
            SuggestedAudioFile suggestedOption_2 = new SuggestedAudioFile(collection_2);

            if (suggestedOption_1.AccuracyType == AccuracyType.Accurate && suggestedOption_2.AccuracyType != AccuracyType.Accurate)
            {
                if (suggestedOption_1.AccuracyScore >= suggestedOption_2.AccuracyScore)
                {
                    lsr.Tokens.SetOriginalSearchStrategy();

                    return(collection_1);
                }
            }

            if (suggestedOption_1.AccuracyType != AccuracyType.Accurate && suggestedOption_2.AccuracyType == AccuracyType.Accurate)
            {
                if (suggestedOption_1.AccuracyScore <= suggestedOption_2.AccuracyScore)
                {
                    return(collection_2);
                }
            }

            //Suggested Files (1 and 2) are either both accurate, or both inaccurate
            if (suggestedOption_1.AccuracyScore >= (suggestedOption_2.AccuracyScore - Globals.SearchStrategySwitchThreshold))  //Preference is given to the original search strategy
            {
                lsr.Tokens.SetOriginalSearchStrategy();

                return(collection_1);
            }
            else
            {
                return(collection_2);
            }
        }
        public SuggestedAudioFile(AudioFileSearchCollection collection)
        {
            _FullPath             = collection.BestOption.LibraryFile.FullPath;
            _SubDirectoriesPath   = collection.BestOption.LibraryFile.SubDirectoriesPath;
            _ModifiedDate         = collection.BestOption.LibraryFile.ModifiedDate;
            _FileSize             = collection.BestOption.LibraryFile.FileSize;
            _TotalPoints          = collection.BestOption.GetTotalPoints();
            _AccuracyScore        = collection.BestOption.AccuracyScore;
            _IsPossiblyWrongCycle = collection.BestOption.IsPossiblyWrongCycle;

            AssignAccuracyType(collection);
        }
        private void AssignAccuracyType(AudioFileSearchCollection collection)
        {
            if (_AccuracyScore >= Globals.AccurateThreshold)
            {
                _AccuracyType = AccuracyType.Accurate;
                _AccuracyNote = Globals.AccurateNote;
            }
            else if (_AccuracyScore >= Globals.QuestionableThreshold)
            {
                _AccuracyType = AccuracyType.Questionable;

                if (collection.BestOption.IsPossiblyWrongTrackNumber == true)
                {
                    //Possibly wrong Track Number?
                    _AccuracyNote = Globals.PossiblyWrongTrackNumber;
                }
                else if (collection.BestOption.GetArtistAlbumPointsRatio() > 70 && collection.BestOption.GetTrackPointsRatio() <= 70)
                {
                    _AccuracyNote = Globals.QuestionableNoteTrack;
                }
                else if (collection.BestOption.GetTrackPointsRatio() > 70 && collection.BestOption.GetArtistAlbumPointsRatio() <= 70)
                {
                    _AccuracyNote = Globals.QuestionableNoteArtistAlbum;
                }
                else
                {
                    _AccuracyNote = Globals.QuestionableNote_Overall;
                }
            }
            else
            {
                _AccuracyType = AccuracyType.HighRisk;

                if (collection.BestOption.GetArtistAlbumPointsRatio() > 70 && collection.BestOption.GetTrackPointsRatio() <= 70)
                {
                    _AccuracyNote = Globals.HighRiskNoteTrack;
                }
                else if (collection.BestOption.GetTrackPointsRatio() > 70 && collection.BestOption.GetArtistAlbumPointsRatio() <= 70)
                {
                    _AccuracyNote = Globals.HighRiskNoteArtistAlbum;
                }
                else
                {
                    _AccuracyNote = Globals.HighRiskNote_Overall;
                }
            }

            if (_AccuracyType == AccuracyType.Accurate)
            {
                SafetyNetChecks(collection);
            }
        }
        private void SafetyNetChecks(AudioFileSearchCollection collection)
        {
            if (collection.AODLoadSheetRow.CharCountArtistAlbumTrackNumberTrack <= Globals.TooFewLSRCharsThreshold)
            {
                //too few characters to guarantee accuracy independant of accuracy score
                _AccuracyType = AccuracyType.Questionable;
                _AccuracyNote = Globals.TooFewLSRCharsNote + collection.AODLoadSheetRow.CharCountArtistAlbumTrackNumberTrack.ToString();
            }
            else if (collection.ChosenFinalPassCount > 1)
            {
                //too many options in final pool in which the file was selected from to guarantee accuracy independant of accuracy score
                _AccuracyType = AccuracyType.Questionable;
                _AccuracyNote = Globals.TooManyFinalOptionsNote + collection.ChosenFinalPassCount.ToString();
            }
            else if (collection.BestOption.IsPossiblyWrongArtistAlbum == true)
            {
                //very low points scored for the Artist or Album, probably a back source file selection?
                _AccuracyType = AccuracyType.Questionable;
                _AccuracyNote = Globals.TooFewArtistAlbumPointsScored;
            }
            else if (collection.BestOption.IsPossiblyWrongTrackNumberTrack == true)
            {
                //very low points scored for the track, probably a back source file selection?
                _AccuracyType = AccuracyType.Questionable;
                _AccuracyNote = Globals.TooFewTrackPointsScored;
            }
            else if (collection.BestOption.IsPossiblyWrongAirline == true)
            {
                //Possibly from the wrong client?
                _AccuracyType = AccuracyType.Questionable;
                _AccuracyNote = Globals.PossiblyWrongAirline;
            }
            else if (collection.BestOption.IsPossiblyWrongCycle == true)
            {
                //Possibly from the wrong cycle?
                _AccuracyType = AccuracyType.Questionable;
                _AccuracyNote = Globals.PossiblyWrongCycle;
            }
            else if (collection.BestOption.IsPossiblyWrongTrackNumber == true)
            {
                string audioType = collection.AODLoadSheetRow.Tokens.AudioTypeTokens.FullToken;

                if (audioType == Globals.CD || audioType == Globals.AUDIOBOOK || audioType == Globals.PLAYLIST)
                {
                    //Possibly wrong Track Number?
                    _AccuracyType = AccuracyType.Questionable;
                    _AccuracyNote = Globals.PossiblyWrongTrackNumber;
                }
            }
        }
        private static AudioFileSearchCollection BackwardsSearch(AudioFileSearchCollection searchCollection, AudioLibrary audioLibrary, TokensCollection tokens)
        {
            //Backwards Search priority:  Track  --->  Artist/Album

            AudioFileOptions pass1 = Track_Pass1(audioLibrary, tokens);

            AudioFileOptions pass2 = ArtistAlbum_Pass2(pass1);

            pass2.FinishAllOptions();

            AudioFileOptions finalPass = pass2.Clone();

            finalPass.TieBreakAudioFileOptions(SearchMethodType.Backwards);

            searchCollection.AssignBackwardsSearchPasses(pass1, pass2, finalPass);

            return(searchCollection);
        }
        private static AudioFileSearchCollection GetSearchCollection(AudioLibrary audioLibrary, AODLoadSheetRow lsr)
        {
            AudioFileSearchCollection searchCollection = new AudioFileSearchCollection(lsr);

            searchCollection = ForwardsSearch(searchCollection, audioLibrary, lsr.Tokens);
            AudioFileOption candidateOption_1 = searchCollection.ForwardsFinalPass.GetCandidateOption();

            searchCollection = BackwardsSearch(searchCollection, audioLibrary, lsr.Tokens);
            AudioFileOption candidateOption_2 = searchCollection.BackwardsFinalPass.GetCandidateOption();

            int bestCandidateOption = ChooseBestCandidateOption(candidateOption_1, candidateOption_2);

            if (bestCandidateOption == 1) //CandidateOption_1
            {
                searchCollection.FinishCollection(SearchMethodType.Forwards);
                return(searchCollection);
            }
            else //CandidateOption_2
            {
                searchCollection.FinishCollection(SearchMethodType.Backwards);
                return(searchCollection);
            }
        }