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 AlbumArtistSearcher : ITrackSearcher
	{
		private readonly IMusicGuide _musicGuide;

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

		public event StatusHandler SearchStatusUpdate;

		private void OnStatusUpdate(string status)
		{
			if (SearchStatusUpdate != null)
				SearchStatusUpdate.Invoke(new StatusEventArgs(status));
		}

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

			var albumResults = ScoreUtility.ScoreResults(_musicGuide.SearchAlbum, trackQuery.AlbumTitle).ToList();
			var artistName = GetArtistName(trackQuery);
			var artistResults = ScoreUtility.ScoreResults(_musicGuide.SearchArtist, artistName);

			if (canellationToken.IsCancellationRequested)
				return null;

			var matchingAlbums = ScoreUtility.Match(
				albumResults, artistResults, 
					(album, artist) =>
						album.ArtistId == artist.ArtistId).ToList();

			if (trackQuery.AlbumPartOfCompilation)
				matchingAlbums = matchingAlbums.Union(
					from album in albumResults
					where 
						album.Obj.ArtistId == null
						|| album.Obj.AlbumTitle.Contains("Soundtrack")
					select album
					).ToList();

			if (canellationToken.IsCancellationRequested)
				return null;

			OnStatusUpdate("Found " + matchingAlbums.Count() + " potential matching albums");

			return (from album in matchingAlbums
			        let tracks = _musicGuide.GetAlbum(album.Obj.AlbumId).Tracks
			        let match = TrackSimilarity.MatchTrack(trackQuery, tracks)
					where match != null
			        select match).FirstOrDefault();
		}

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