using System;
using System.Text.RegularExpressions;

namespace LeafWeb.Core.Utility
{
	public static class TimeSpanExtensions
	{
		private const string Month = "month";
		private const string MonthAbr = "mo.";
		private const string Day = "day";
		private const string DayAbr = "day";
		private const string Hour = "hour";
		private const string HourAbr = "hr.";
		private const string Minute = "minute";
		private const string MinuteAbr = "min.";
		private const string Second = "second";
		private const string SecondAbr = "sec.";
		private static Regex PluralizeRegex = new Regex(@"^([^\.]*)(\.?)$", RegexOptions.Compiled);

		public static string ToReadableString(this TimeSpan span)
		{
			Func<int, string> pluralize = i => i > 1 ? "s" : string.Empty;
			// ReSharper disable once UseStringInterpolation
			var formatted = string.Format("{0}{1}{2}{3}",
				span.Duration().Days > 0 ? $"{span.Days:0} day{pluralize(span.Days)}, " : string.Empty,
				span.Duration().Hours > 0 ? $"{span.Hours:0} hour{pluralize(span.Hours)}, " : string.Empty,
				span.Duration().Minutes > 0 ? $"{span.Minutes:0} minute{pluralize(span.Minutes)}, " : string.Empty,
				span.Duration().Seconds > 0 ? $"{span.Seconds:0} second{pluralize(span.Seconds)}" : string.Empty);

			if (formatted.EndsWith(", ")) formatted = formatted.Substring(0, formatted.Length - 2);

			if (string.IsNullOrEmpty(formatted)) formatted = "0 seconds";

			return formatted;
		}

		public static string ToRoundedReadableString(this TimeSpan span, bool abbreviation = true)
		{
			Func<int, string, string> pluralize =
				(i, s) => i > 1 ? PluralizeRegex.Replace(s, "$1s$2") : s;

			Func<int, string, string> formatTime = (i, s) => $"{i:0} {pluralize(i, s)}";

			if (span.Duration().Days > 90)
				return formatTime(span.Days/30, abbreviation ? MonthAbr : Month);
			if (span.Duration().Days > 0)
				return formatTime(span.Days, abbreviation ? DayAbr : Day);
			if (span.Duration().Hours > 0)
				return formatTime(span.Hours, abbreviation ? HourAbr : Hour);
			if (span.Duration().Minutes > 0)
				return formatTime(span.Minutes, abbreviation ? MinuteAbr : Minute);
			if (span.Duration().Seconds > 0)
				return formatTime(span.Seconds, abbreviation ? SecondAbr : Second);

			return "0 seconds";
		}
	}
}
