using System.Linq;
using System.Threading;
using MusicMetaTagger.Core.Model;
using MusicMetaTagger.Core.Queries;
using MusicMetaTagger.Core.Services;
using MusicMetaTagger.Core.Utility;

namespace MusicMetaTagger.Client.AllMusicGuide.Services.Searchers
{
	public class SongArtistSearcher : ITrackSearcher
	{
		private readonly IMusicGuide _musicGuide;

		public SongArtistSearcher(IMusicGuide musicGuide)
		{
			_musicGuide = musicGuide;
		}

		public event StatusHandler SearchStatusUpdate;

		public Track SearchTrack(TrackQuery trackQuery, CancellationToken canellationToken)
		{
			if (string.IsNullOrEmpty(trackQuery.TrackTitle)
			    || string.IsNullOrEmpty(trackQuery.ArtistName))
				return null;

			var songResults = ScoreUtility.ScoreResults(_musicGuide.SearchSong, trackQuery.TrackTitle);
			var artistName = GetArtistName(trackQuery);
			var artistResults = ScoreUtility.ScoreResults(_musicGuide.SearchArtist, artistName);

			if (canellationToken.IsCancellationRequested)
				return null;

			var matchingSongs = ScoreUtility.Match(songResults, artistResults, (s, a) => s.ArtistId == a.ArtistId).ToList();

			foreach (var song in matchingSongs)
			{
				foreach (var album in _musicGuide.GetSong(song.Obj.SongId).AppearsOnAlbum)
				{
					if (canellationToken.IsCancellationRequested)
						return null;

					var tracks = _musicGuide.GetAlbum(album.AlbumId).Tracks;
					var match = TrackSimilarity.MatchTrack(trackQuery, tracks);
					if (match != null) return match;
				}
			}
			return null;
		}

		private static string GetArtistName(TrackQuery trackQuery)
		{
			var artistName = trackQuery.ArtistName;
			if (!string.IsNullOrEmpty(trackQuery.AlbumArtistName) && !trackQuery.AlbumArtistName.Contains("Various"))
				artistName = trackQuery.AlbumArtistName;
			return artistName;
		}
	}
}