using UnityEngine;

//-----------------------------------------------------------------------------
// Copyright 2015-2022 RenderHeads Ltd.  All rights reserved.
//-----------------------------------------------------------------------------

namespace RenderHeads.Media.AVProVideo
{
	public partial class MediaPlayer : MonoBehaviour
	{

#region Support for Time Scale
#if AVPROVIDEO_BETA_SUPPORT_TIMESCALE
		// Adjust this value to get faster performance but may drop frames.
		// Wait longer to ensure there is enough time for frames to process
		private const float TimeScaleTimeoutMs = 20f;
		private bool _timeScaleIsControlling;
		private double _timeScaleVideoTime;

		private void UpdateTimeScale()
		{
			if (Time.timeScale != 1f || Time.captureFramerate != 0)
			{
				if (_controlInterface.IsPlaying())
				{
					_controlInterface.Pause();
					_timeScaleIsControlling = true;
					_timeScaleVideoTime = _controlInterface.GetCurrentTime();
				}

				if (_timeScaleIsControlling)
				{
					// Progress time
					_timeScaleVideoTime += Time.deltaTime;

					// Handle looping
					if (_controlInterface.IsLooping() && _timeScaleVideoTime >= Info.GetDuration())
					{
						// TODO: really we should seek to (_timeScaleVideoTime % Info.GetDuration())
						_timeScaleVideoTime = 0.0;
					}

					int preSeekFrameCount = TextureProducer.GetTextureFrameCount();

					// Seek to the new time
					{
						double preSeekTime = Control.GetCurrentTime();

						// Seek
						_controlInterface.Seek(_timeScaleVideoTime);

						// Early out, if after the seek the time hasn't changed, the seek was probably too small to go to the next frame.
						// TODO: This behaviour may be different on other platforms (not Windows) and needs more testing.
						if (Mathf.Approximately((float)preSeekTime, (float)_controlInterface.GetCurrentTime()))
						{
							return;
						}
					}

					// Wait for the new frame to arrive
					if (!_controlInterface.WaitForNextFrame(GetDummyCamera(), preSeekFrameCount))
					{
						// If WaitForNextFrame fails (e.g. in android single threaded), we run the below code to asynchronously wait for the frame
						System.DateTime startTime = System.DateTime.Now;
						int lastFrameCount = TextureProducer.GetTextureFrameCount();

						while (_controlInterface != null && (System.DateTime.Now - startTime).TotalMilliseconds < (double)TimeScaleTimeoutMs)
						{
							_playerInterface.Update();
							_playerInterface.Render();
							GetDummyCamera().Render();
							if (lastFrameCount != TextureProducer.GetTextureFrameCount())
							{
								break;
							}
						}
					}
				}
			}
			else
			{
				// Restore playback when timeScale becomes 1
				if (_timeScaleIsControlling)
				{
					_controlInterface.Play();
					_timeScaleIsControlling = false;
				}
			}
		}
#endif
#endregion // Support for Time Scale
	}
}