// <auto-generated>
/*
 * API ebike_v1 1.0.0
 *
 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 *
 * The version of the OpenAPI document: 1.0.0
 * Generated by: https://github.com/openapitools/openapi-generator.git
 */

#nullable enable

using System;

namespace Org.OpenAPITools.Client
{
    /// <summary>
    /// The base for all tokens.
    /// </summary>
    public abstract class TokenBase
    {
        private DateTime _nextAvailable = DateTime.UtcNow;
        private readonly object _nextAvailableLock = new object();
        private readonly System.Timers.Timer _timer = new System.Timers.Timer();

        internal TimeSpan? Timeout { get; set; }

        /// <summary>
        /// Delegate for token availability notification events.
        /// </summary>
        /// <param name="sender">The token that became available.</param>
        public delegate void TokenBecameAvailableEventHandler(object sender);

        /// <summary>
        /// Event raised when a rate-limited token becomes available for use.
        /// </summary>
        public event TokenBecameAvailableEventHandler? TokenBecameAvailable;

        /// <summary>
        /// Initialize a TokenBase object.
        /// </summary>
        /// <param name="timeout"></param>
        internal TokenBase(TimeSpan? timeout = null)
        {
            Timeout = timeout;
            
            if (Timeout != null)
                StartTimer(Timeout.Value);
        }

        /// <summary>
        /// Starts the token's timer
        /// </summary>
        /// <param name="timeout"></param>
        internal void StartTimer(TimeSpan timeout)
        {
            Timeout = timeout;
            _timer.Interval = Timeout.Value.TotalMilliseconds;
            _timer.Elapsed += OnTimer;
            _timer.AutoReset = true;
            _timer.Start();
        }

        /// <summary>
        /// Returns true while the token is rate limited.
        /// </summary>
        public bool IsRateLimited { get { lock (_nextAvailableLock) return _nextAvailable > DateTime.UtcNow; } }

        /// <summary>
        /// Triggered when the server returns status code TooManyRequests
        /// Once triggered the local timeout will be extended an arbitrary length of time.
        /// </summary>
        public void BeginRateLimit()
        {
            lock(_nextAvailableLock)
                _nextAvailable = DateTime.UtcNow.AddSeconds(5);
        }

        private void OnTimer(object? sender, System.Timers.ElapsedEventArgs e)
        {
            if (!IsRateLimited)
                TokenBecameAvailable?.Invoke(this);
        }
    }
}
