/* Copyright (C) Itseez3D, Inc. - All Rights Reserved
* You may not use this file except in compliance with an authorized license
* Unauthorized copying of this file, via any medium is strictly prohibited
* Proprietary and confidential
* UNLESS REQUIRED BY APPLICABLE LAW OR AGREED BY ITSEEZ3D, INC. IN WRITING, SOFTWARE DISTRIBUTED UNDER THE LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED
* See the License for the specific language governing permissions and limitations under the License.
* Written by Itseez3D, Inc. <support@avatarsdk.com>, October 2026
*/

using System;
using System.Globalization;

namespace AvatarSDKMove
{
	public class GenerationTimeEstimate
	{
		private static readonly TimeSpan TimePerAnimationSecond = TimeSpan.FromMinutes(1);
		private static readonly TimeSpan DefaultTotalTime = TimeSpan.FromMinutes(5);

		private readonly DateTime startTimeUtc;
		private readonly TimeSpan totalTime;

		public GenerationTimeEstimate(string createdOn, float duration)
		{
			if (!DateTime.TryParse(createdOn, CultureInfo.InvariantCulture,
				DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out startTimeUtc))
				startTimeUtc = DateTime.UtcNow;

			totalTime = duration > 0 ? TimeSpan.FromTicks((long)(TimePerAnimationSecond.Ticks * duration)) : DefaultTotalTime;
		}

		public TimeSpan TimeLeft
		{
			get
			{
				TimeSpan left = totalTime - (DateTime.UtcNow - startTimeUtc);
				if (left > totalTime)
					return totalTime;
				return left < TimeSpan.Zero ? TimeSpan.Zero : left;
			}
		}

		public string FormatStatus(string status)
		{
			bool isQueued = string.Equals(status, "Queued", StringComparison.OrdinalIgnoreCase)
				|| string.Equals(status, "Pending", StringComparison.OrdinalIgnoreCase);
			return isQueued ? "Queued: " + FormatQueuedTime() : "Computing: " + FormatTimeLeft();
		}

		public string FormatQueuedTime()
		{
			// Waiting in the queue does not reduce the expected computation time.
			int minutes = Math.Max(1, (int)Math.Ceiling(totalTime.TotalMinutes));
			return string.Format(CultureInfo.InvariantCulture, "> {0} {1}", minutes, minutes == 1 ? "minute" : "minutes");
		}

		public string FormatTimeLeft()
		{
			TimeSpan left = TimeLeft;
			if (left <= TimeSpan.Zero)
				return "almost done";
			if (left < TimeSpan.FromMinutes(1))
				return "less than a minute left";
			return string.Format(CultureInfo.InvariantCulture, "about {0} min left", (int)Math.Ceiling(left.TotalMinutes));
		}
	}
}
