﻿#pragma warning disable CA1024

namespace Dike.Core.Test.Runtime.Caching
{
    using Dike.Core.Runtime.Caching;
    using Shouldly;
    using System;
    using System.Diagnostics.CodeAnalysis;
    using System.Threading.Tasks;
    using Xunit;

    /// <summary>
    /// Unit test for the <see cref="Core.Runtime.Caching.CacheExtensions"/> class.
    /// </summary>
    [ExcludeFromCodeCoverage]
    public class CacheExtensionsTest
    {
        #region Methods

        /// <summary>
        /// Unit test of the <see cref="CacheExtensions.GetItem(ICache, string, Func{object})"/>,
        /// <see cref="CacheExtensions.GetItem{TKey, TValue}(ICache, TKey, Func{TKey, TValue})"/>,
        /// <see cref="CacheExtensions.GetItem{TKey, TValue}(ICache, TKey, Func{TValue})"/>,
        /// <see cref="CacheExtensions.GetItemAsync(ICache, string, Func{Task{object}})"/>,
        /// <see cref="CacheExtensions.GetItemAsync{TKey, TValue}(ICache, TKey, Func{Task{TValue}})"/> and
        /// <see cref="CacheExtensions.GetItemAsync{TKey, TValue}(ICache, TKey, Func{TKey, Task{TValue}})"/> methods.
        /// </summary>
        /// <returns>A task that represents the asynchronous operation.</returns>
        [Fact]
        public async Task GetItem_Should_Pass()
        {
            using (Cache cache = new Cache("TestCache"))
            {
                string syncItem = (string)cache.GetItem("Key", () => SyncFactory());
                syncItem.ShouldBe("Value");
                syncItem = (string)cache.GetItem<string, object>("Key", () => SyncFactory());
                syncItem.ShouldBe("Value");

                Func<Task<object>> asyncFunc;
                asyncFunc = AsyncFactory;

                string asyncItem = (string)(await cache.GetItemAsync("Key", () => asyncFunc()).ConfigureAwait(false));
                asyncItem.ShouldBe("Value");
                asyncItem = (string)(await cache.GetItemAsync<string, object>("Key2", () => asyncFunc()).ConfigureAwait(false));
                asyncItem.ShouldBe("Value");
            }
        }

        /// <summary>
        /// Unit test of the <see cref="CacheExtensions.GetItemOrDefault{TKey, TValue}(ICache, TKey)"/> and
        /// <see cref="CacheExtensions.GetItemOrDefaultAsync{TKey, TValue}(ICache, TKey)"/> methods.
        /// </summary>
        /// <returns>A task that represents the asynchronous operation.</returns>
        [Fact]
        public async Task GetItemOrDefault_Should_Pass()
        {
            using (Cache cache = new Cache("TestCache"))
            {
                string item = cache.GetItemOrDefault<string, string>("Key");
                item.ShouldBeNull();
                item = await cache.GetItemOrDefaultAsync<string, string>("Key").ConfigureAwait(false);
                item.ShouldBeNull();
            }
        }

        /// <summary>
        /// Asynchronously factory call to create cache item.
        /// </summary>
        /// <returns>A task that represents the asynchronous operation.
        /// The task result contains the cached item.</returns>
        [ExcludeFromCodeCoverage]
        private async Task<object> AsyncFactory()
            => await Task.FromResult("Value").ConfigureAwait(false);

        /// <summary>
        /// Factory call to create cache item.
        /// </summary>
        /// <returns>The cache item.</returns>
        [ExcludeFromCodeCoverage]
        private object SyncFactory()
            => "Value";

        #endregion Methods
    }
}

#pragma warning restore CA1024
