using System.Collections.Concurrent;
using Quadarax.Foundation.Core.Business.Processor.Dependencies.Value.Extensions;
using Quadarax.Foundation.Core.Business.Processor.Enums;
using Quadarax.Foundation.Core.Business.Processor.Task;
using Quadarax.Foundation.Core.Data;
using Quadarax.Foundation.Core.Data.Extensions;
using Quadarax.Foundation.Core.Object;

namespace Quadarax.Foundation.Core.Business.Processor.Providers
{
    public class InMemoryStorageProvider : ProcessorStorageProvider
    {
        #region *** Private fields ***
        private readonly IDictionary<long, ITaskItemData> _cache = new ConcurrentDictionary<long, ITaskItemData>();
        #endregion

        #region *** Overrides ***
        protected override void OnDisposing()
        {
            _cache.Clear();
        }

        public override IQueryable<ITaskItemData> Query(IPaging paging, params ProcessStatusEnum[] statuses)
        {
            return _cache.Values.Where(x=>x.Status.In(statuses)).AsQueryable().Page(paging);
        }

        protected override void OnOpen()
        {
        }

        protected override void OnClose()
        {
        }

        protected override bool OnEnsureStorage()
        {
            return false;
        }

        protected override ITaskIdentifier OnCreate(ITaskItemData item)
        {
            var id = GetNextId();
            ((TaskItem)item).Id = id;
            _cache.TryAdd(id, item);
            return item;
        }

        protected override ITaskItemData[] OnGet(ITaskIdentifier[] ids)
        {
            var result = ids.Select(id => _cache[id.Id]).ToList();
            return result.ToArray();
        }

        protected override void OnDeleteOne(ITaskItemData item)
        {
            _cache.Remove(item.Id);
        }

        protected override void OnSetOne(ITaskItemData item)
        {
            var existing = (TaskItem) _cache[item.Id];
            existing.CopyFrom(item);
        }
        #endregion

        #region *** Private operations ***
        private long GetNextId()
        {
            return _cache.Keys.Any() ? _cache.Keys.Max() + 1 : 1;
        }
        #endregion 

    }
}
