using qdr.fnd.core.pqueue.Enums;
using Quadarax.Foundation.Core.Data;

namespace qdr.fnd.core.pqueue
{
    public interface IPsQueue : IDisposable
    {
        #region *** Properties ***
        /// <summary>
        /// Flag determines if the queue is running. Means if <see cref="Start"/> was called and <see cref="Stop"/> was not called.
        /// </summary>
        bool IsRunning { get; }
        #endregion

        #region *** Operations ***
        /// <summary>
        /// Starts the queue engine to processing queue items. If the queue is already running, the method throws an exception.
        /// <exception cref="CodeExeption"></exception>
        /// </summary>
        void Start();
        void Stop();

        /// <summary>
        /// Add new item to queue described by <paramref name="item"/>
        /// </summary>
        /// <param name="item">Queue item decriptor</param>
        /// <returns>If succeed returns item identifier (itemId)</returns>
        string EnQueueItem(IPsQueueItemDescriptor item);

        /// <summary>
        /// Get specific queue item (full) by its identifier <paramref name="itemId"/> no matter what <see cref="IPsQueueItem.Status"/> set.
        /// Item must exists, otherwise throws exception.
        /// </summary>
        /// <param name="itemId">process item identifier.</param>
        /// <returns>Full queue item (incl. status history).</returns>
        IPsQueueItem GetQueueItem(string itemId);
        
        /// <summary>
        /// Schedules item to start immediately. Ignores ValidFrom and status exept <see cref="PsStatusEnum.Started"/>,<see cref="PsStatusEnum.Stopped"/>,<see cref="PsStatusEnum.Expired"/>.
        /// Operation resets <see cref="IPsQueueItem.Status"/>, <see cref="IPsQueueItem.AttemptsLeft"/>, <see cref="IPsQueueItemDescriptor.ValidFrom"/>, <see cref="IPsQueueItemDescriptor.ValidTo"/>, <see cref="IPsQueueItemDescriptor.Priority"/>, <see cref="IPsQueueItem.Started"/>, <see cref="IPsQueueItem.Finished"/>
        /// </summary>
        /// <param name="itemId">process item identifier.</param>
        /// <param name="emitter">Sign who emmits request.</param>
        void ForceStartQueueItem(string itemId, string emitter);

        /// <summary>
        /// Schedules item to stops immediately and set <see cref="IPsQueueItem.Status"/> to <see cref="PsStatusEnum.Stopped"/>.
        /// If item currently processing, kill process and left (skip decrement) attempt counter.
        /// Ignores ValidFrom and status exept <see cref="PsStatusEnum.Expired"/>,<see cref="PsStatusEnum.DoneOk"/>,<see cref="PsStatusEnum.DoneFail"/>.
        /// </summary>
        /// <param name="itemId">process item identifier.</param>
        /// <param name="emitter">Sign who emmits request.</param>
        void ForceStopQueueItem(string itemId, string emitter);

        /// <summary>
        /// Schedules item to pause immediately and set <see cref="IPsQueueItem.Status"/> to <see cref="PsStatusEnum.Paused"/> and can be resumed by use <see cref="IPsQueue.Start"/>.
        /// If item currently processing, waits to next attempt, then set to paused.
        /// Ignores ValidFrom and status exept <see cref="PsStatusEnum.Expired"/>,<see cref="PsStatusEnum.DoneOk"/>,<see cref="PsStatusEnum.DoneFail"/>,<see cref="PsStatusEnum.Stopped"/>.
        /// </summary>
        /// <param name="itemId">process item identifier.</param>
        /// <param name="emitter">Sign who emmits request.</param>
        void PauseQueueItem(string itemId, string emmiter);

        /// <summary>
        /// Schedules item to start or resume and set <see cref="IPsQueueItem.Status"/> to <see cref="PsStatusEnum.Started"/>.
        /// </summary>
        /// <param name="itemId">process item identifier.</param>
        /// <param name="emitter">Sign who emmits request.</param>
        /// <param name="isImmediate">If set to true, reshedule item to run immediately (change <see cref="IPsQueueItemDescriptor.ValidFrom"/>, <see cref="IPsQueueItemDescriptor.ValidTo"/>, <see cref="IPsQueueItemDescriptor.Priority"/></param>
        void StartQueueItem(string itemId, string emmiter, bool isImmediate);

        /// <summary>
        /// Returns query (queryable) in process queue by custom specification.
        /// </summary>
        /// <param name="paging">Paging specification for query.</param>
        /// <param name="owner">Owner identifier. If null then condition is skipped.</param>
        /// <param name="ownerRef">Owner reference identifier. If null then condition is skipped.</param>
        /// <param name="includeTransient">If set includes transient states. Default set to False.</param>
        /// <param name="statuses">Collection of requested complex statuses.</param>
        /// <returns>Queryable result (item is <see cref="IPsQueueItem"/>) collection limited by <paramref name="paging"/></returns>
        IQueryable<IPsQueueItem> QueryQueueItems(IPaging paging, string? owner, string? ownerRef, bool includeTransient = false, params PsStatusEnum[] statuses);

        #endregion
    }
}
