using System;
using System.Collections.Generic;
using System.Linq;
using MusicMetaTagger.Core.Model;
using MusicMetaTagger.Core.Utility;

namespace MusicMetaTagger.Core.Services
{
	public static class TrackSimilarity
	{
		public static double Similarity(ITrack t1, ITrack t2)
		{
			var scores = new List<double>();

			var titleCompare = StringUtility.Similarity(t1.TrackTitle, t2.TrackTitle);
			// weigh the title heavily
			for (var i = 0; i < 3; i++)
				scores.Add(titleCompare);

			// compare track number
			if (t1.TrackNumber > 0 && t2.TrackNumber > 0)
			{
				var trackNumberCompare = t1.TrackNumber == t2.TrackNumber ? 1.0 : 0;
				scores.Add(trackNumberCompare);
			}

			// compare the track length
			if (t1.TrackLength.TotalSeconds > 0 && t2.TrackLength.TotalSeconds > 0)
			{
				var timeCompare = 1.0 - 1.0 * 
					Math.Abs(t1.TrackLength.TotalSeconds - t2.TrackLength.TotalSeconds) /
				    Math.Max(t1.TrackLength.TotalSeconds, t2.TrackLength.TotalSeconds);
				scores.Add(timeCompare);
			}

			return scores.Average();
		}

		public static Track MatchTrack(ITrack needle, IEnumerable<Track> haystack, double matchThreshold = .75)
		{
			var scoredTracks =
					(from hay in haystack
					 let similarity = Similarity(hay, needle)
					 select new ScoreContainer<Track>(hay, similarity)).ToList();

			var matchTrack =
				scoredTracks
				.Where(t => t.Score >= matchThreshold)
				.OrderByDescending(t => t.Score)
				.FirstOrDefault();

			return matchTrack != null ? matchTrack.Obj : null;
		}
	}
}