/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// ReSharper disable UnusedAutoPropertyAccessor.Local
namespace Apache.Ignite.AspNet.Tests
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using Apache.Ignite.AspNet.Impl;
    using Apache.Ignite.Core;
    using Apache.Ignite.Core.Cache;
    using Apache.Ignite.Core.Cache.Configuration;
    using Apache.Ignite.Core.Cache.Expiry;
    using Apache.Ignite.Core.Cache.Query;
    using Apache.Ignite.Core.Cache.Query.Continuous;
    using Apache.Ignite.Core.Cluster;
    using NUnit.Framework;

    /// <summary>
    /// Tests for <see cref="ExpiryCacheHolder{TK,TV}"/>.
    /// </summary>
    public class ExpiryCacheHolderTest
    {
        /// <summary>
        /// Tests the expiry policy.
        /// </summary>
        [Test]
        public void TestExpiryPolicy()
        {
            var cache = new CacheEx();

            Assert.IsNull(cache.ExpiryPolicy);

            var holder = new ExpiryCacheHolder<int, int>(cache);

            // Check same cache for same expiry.
            var cache1 = (CacheEx) holder.GetCacheWithExpiry(15);

            CheckExpiry(TimeSpan.FromSeconds(15), cache1);
            Assert.AreNotSame(cache, cache1);
            Assert.AreSame(cache1, holder.GetCacheWithExpiry(15));

            // Check rounding.
            var cache2 = (CacheEx) holder.GetCacheWithExpiry(DateTime.UtcNow.AddSeconds(15.1));
            Assert.AreSame(cache1, cache2);

            // Check no expiration.
            var cache3 = (CacheEx) holder.GetCacheWithExpiry(DateTime.MaxValue);
            Assert.AreSame(cache, cache3);
        }

        /// <summary>
        /// Checks the expiry.
        /// </summary>
        private static void CheckExpiry(TimeSpan timeSpan, CacheEx cache)
        {
            Assert.AreEqual(timeSpan, cache.ExpiryPolicy.GetExpiryForCreate());
            Assert.IsNull(cache.ExpiryPolicy.GetExpiryForUpdate());
            Assert.IsNull(cache.ExpiryPolicy.GetExpiryForAccess());
        }

        /// <summary>
        /// Test cache implementation.
        /// </summary>
        private class CacheEx : ICache<int, int>
        {
            public IExpiryPolicy ExpiryPolicy { get; set; }

            public IEnumerator<ICacheEntry<int, int>> GetEnumerator()
            {
                throw new NotImplementedException();
            }

            IEnumerator IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }

            public string Name { get; private set; }

            public IIgnite Ignite { get; private set; }

            public CacheConfiguration GetConfiguration()
            {
                throw new NotImplementedException();
            }

            public bool IsEmpty()
            {
                throw new NotImplementedException();
            }

            public bool IsKeepBinary { get; private set; }

            public bool IsAllowAtomicOpsInTx { get; private set; }

            public ICache<int, int> WithSkipStore()
            {
                throw new NotImplementedException();
            }

            public ICache<int, int> WithExpiryPolicy(IExpiryPolicy plc)
            {
                return new CacheEx {ExpiryPolicy = plc};
            }

            public ICache<TK1, TV1> WithKeepBinary<TK1, TV1>()
            {
                throw new NotImplementedException();
            }

            public ICache<int, int> WithAllowAtomicOpsInTx()
            {
                throw new NotImplementedException();
            }

            public void LoadCache(ICacheEntryFilter<int, int> p, params object[] args)
            {
                throw new NotImplementedException();
            }

            public Task LoadCacheAsync(ICacheEntryFilter<int, int> p, params object[] args)
            {
                throw new NotImplementedException();
            }

            public void LocalLoadCache(ICacheEntryFilter<int, int> p, params object[] args)
            {
                throw new NotImplementedException();
            }

            public Task LocalLoadCacheAsync(ICacheEntryFilter<int, int> p, params object[] args)
            {
                throw new NotImplementedException();
            }

            public void LoadAll(IEnumerable<int> keys, bool replaceExistingValues)
            {
                throw new NotImplementedException();
            }

            public Task LoadAllAsync(IEnumerable<int> keys, bool replaceExistingValues)
            {
                throw new NotImplementedException();
            }

            public bool ContainsKey(int key)
            {
                throw new NotImplementedException();
            }

            public Task<bool> ContainsKeyAsync(int key)
            {
                throw new NotImplementedException();
            }

            public bool ContainsKeys(IEnumerable<int> keys)
            {
                throw new NotImplementedException();
            }

            public Task<bool> ContainsKeysAsync(IEnumerable<int> keys)
            {
                throw new NotImplementedException();
            }

            public int LocalPeek(int key, params CachePeekMode[] modes)
            {
                throw new NotImplementedException();
            }

            public bool TryLocalPeek(int key, out int value, params CachePeekMode[] modes)
            {
                throw new NotImplementedException();
            }

            public int this[int key]
            {
                get { throw new NotImplementedException(); }
                set { throw new NotImplementedException(); }
            }

            public int Get(int key)
            {
                throw new NotImplementedException();
            }

            public Task<int> GetAsync(int key)
            {
                throw new NotImplementedException();
            }

            public bool TryGet(int key, out int value)
            {
                throw new NotImplementedException();
            }

            public Task<CacheResult<int>> TryGetAsync(int key)
            {
                throw new NotImplementedException();
            }

            public ICollection<ICacheEntry<int, int>> GetAll(IEnumerable<int> keys)
            {
                throw new NotImplementedException();
            }

            public Task<ICollection<ICacheEntry<int, int>>> GetAllAsync(IEnumerable<int> keys)
            {
                throw new NotImplementedException();
            }

            public void Put(int key, int val)
            {
                throw new NotImplementedException();
            }

            public Task PutAsync(int key, int val)
            {
                throw new NotImplementedException();
            }

            public CacheResult<int> GetAndPut(int key, int val)
            {
                throw new NotImplementedException();
            }

            public Task<CacheResult<int>> GetAndPutAsync(int key, int val)
            {
                throw new NotImplementedException();
            }

            public CacheResult<int> GetAndReplace(int key, int val)
            {
                throw new NotImplementedException();
            }

            public Task<CacheResult<int>> GetAndReplaceAsync(int key, int val)
            {
                throw new NotImplementedException();
            }

            public CacheResult<int> GetAndRemove(int key)
            {
                throw new NotImplementedException();
            }

            public Task<CacheResult<int>> GetAndRemoveAsync(int key)
            {
                throw new NotImplementedException();
            }

            public bool PutIfAbsent(int key, int val)
            {
                throw new NotImplementedException();
            }

            public Task<bool> PutIfAbsentAsync(int key, int val)
            {
                throw new NotImplementedException();
            }

            public CacheResult<int> GetAndPutIfAbsent(int key, int val)
            {
                throw new NotImplementedException();
            }

            public Task<CacheResult<int>> GetAndPutIfAbsentAsync(int key, int val)
            {
                throw new NotImplementedException();
            }

            public bool Replace(int key, int val)
            {
                throw new NotImplementedException();
            }

            public Task<bool> ReplaceAsync(int key, int val)
            {
                throw new NotImplementedException();
            }

            public bool Replace(int key, int oldVal, int newVal)
            {
                throw new NotImplementedException();
            }

            public Task<bool> ReplaceAsync(int key, int oldVal, int newVal)
            {
                throw new NotImplementedException();
            }

            public void PutAll(IEnumerable<KeyValuePair<int, int>> vals)
            {
                throw new NotImplementedException();
            }

            public Task PutAllAsync(IEnumerable<KeyValuePair<int, int>> vals)
            {
                throw new NotImplementedException();
            }

            public void LocalEvict(IEnumerable<int> keys)
            {
                throw new NotImplementedException();
            }

            public void Clear()
            {
                throw new NotImplementedException();
            }

            public Task ClearAsync()
            {
                throw new NotImplementedException();
            }

            public void Clear(int key)
            {
                throw new NotImplementedException();
            }

            public Task ClearAsync(int key)
            {
                throw new NotImplementedException();
            }

            public void ClearAll(IEnumerable<int> keys)
            {
                throw new NotImplementedException();
            }

            public Task ClearAllAsync(IEnumerable<int> keys)
            {
                throw new NotImplementedException();
            }

            public void LocalClear(int key)
            {
                throw new NotImplementedException();
            }

            public void LocalClearAll(IEnumerable<int> keys)
            {
                throw new NotImplementedException();
            }

            public bool Remove(int key)
            {
                throw new NotImplementedException();
            }

            public Task<bool> RemoveAsync(int key)
            {
                throw new NotImplementedException();
            }

            public bool Remove(int key, int val)
            {
                throw new NotImplementedException();
            }

            public Task<bool> RemoveAsync(int key, int val)
            {
                throw new NotImplementedException();
            }

            public void RemoveAll(IEnumerable<int> keys)
            {
                throw new NotImplementedException();
            }

            public Task RemoveAllAsync(IEnumerable<int> keys)
            {
                throw new NotImplementedException();
            }

            public void RemoveAll()
            {
                throw new NotImplementedException();
            }

            public Task RemoveAllAsync()
            {
                throw new NotImplementedException();
            }

            public int GetLocalSize(params CachePeekMode[] modes)
            {
                throw new NotImplementedException();
            }

            public int GetSize(params CachePeekMode[] modes)
            {
                throw new NotImplementedException();
            }

            public Task<int> GetSizeAsync(params CachePeekMode[] modes)
            {
                throw new NotImplementedException();
            }

            public long GetSizeLong(params CachePeekMode[] modes)
            {
                throw new NotImplementedException();
            }

            public long GetSizeLong(int partition, params CachePeekMode[] modes)
            {
                throw new NotImplementedException();
            }

            public Task<long> GetSizeLongAsync(params CachePeekMode[] modes)
            {
                throw new NotImplementedException();
            }

            public Task<long> GetSizeLongAsync(int partition, params CachePeekMode[] modes)
            {
                throw new NotImplementedException();
            }

            public long GetLocalSizeLong(params CachePeekMode[] modes)
            {
                throw new NotImplementedException();
            }

            public long GetLocalSizeLong(int partition, params CachePeekMode[] modes)
            {
                throw new NotImplementedException();
            }

            public IQueryCursor<ICacheEntry<int, int>> Query(QueryBase qry)
            {
                throw new NotImplementedException();
            }

            public IFieldsQueryCursor Query(SqlFieldsQuery qry)
            {
                throw new NotImplementedException();
            }

            public IQueryCursor<IList> QueryFields(SqlFieldsQuery qry)
            {
                throw new NotImplementedException();
            }

            public IContinuousQueryHandle QueryContinuous(ContinuousQuery<int, int> qry)
            {
                throw new NotImplementedException();
            }

            public IContinuousQueryHandle<ICacheEntry<int, int>> QueryContinuous(ContinuousQuery<int, int> qry, QueryBase initialQry)
            {
                throw new NotImplementedException();
            }

            public IContinuousQueryHandleFields QueryContinuous(ContinuousQuery<int, int> qry, SqlFieldsQuery initialQry)
            {
                throw new NotImplementedException();
            }

            public IEnumerable<ICacheEntry<int, int>> GetLocalEntries(params CachePeekMode[] peekModes)
            {
                throw new NotImplementedException();
            }

            public TRes Invoke<TArg, TRes>(int key, ICacheEntryProcessor<int, int, TArg, TRes> processor, TArg arg)
            {
                throw new NotImplementedException();
            }

            public Task<TRes> InvokeAsync<TArg, TRes>(int key, ICacheEntryProcessor<int, int, TArg, TRes> processor, TArg arg)
            {
                throw new NotImplementedException();
            }

            public ICollection<ICacheEntryProcessorResult<int, TRes>> InvokeAll<TArg, TRes>(IEnumerable<int> keys, ICacheEntryProcessor<int, int, TArg, TRes> processor, TArg arg)
            {
                throw new NotImplementedException();
            }

            public Task<ICollection<ICacheEntryProcessorResult<int, TRes>>> InvokeAllAsync<TArg, TRes>(IEnumerable<int> keys, ICacheEntryProcessor<int, int, TArg, TRes> processor, TArg arg)
            {
                throw new NotImplementedException();
            }

            public ICacheLock Lock(int key)
            {
                throw new NotImplementedException();
            }

            public ICacheLock LockAll(IEnumerable<int> keys)
            {
                throw new NotImplementedException();
            }

            public bool IsLocalLocked(int key, bool byCurrentThread)
            {
                throw new NotImplementedException();
            }

            public ICacheMetrics GetMetrics()
            {
                throw new NotImplementedException();
            }

            public ICacheMetrics GetMetrics(IClusterGroup clusterGroup)
            {
                throw new NotImplementedException();
            }

            public ICacheMetrics GetLocalMetrics()
            {
                throw new NotImplementedException();
            }

            public void EnableStatistics(bool enabled)
            {
                throw new NotImplementedException();
            }

            public void ClearStatistics()
            {
                throw new NotImplementedException();
            }

            public Task Rebalance()
            {
                throw new NotImplementedException();
            }

            public ICache<int, int> WithNoRetries()
            {
                throw new NotImplementedException();
            }

            public ICache<int, int> WithPartitionRecover()
            {
                throw new NotImplementedException();
            }

            public ICollection<int> GetLostPartitions()
            {
                throw new NotImplementedException();
            }

            public IQueryMetrics GetQueryMetrics()
            {
                throw new NotImplementedException();
            }

            public void ResetQueryMetrics()
            {
                throw new NotImplementedException();
            }

            public void PreloadPartition(int partition)
            {
                throw new NotImplementedException();
            }

            public Task PreloadPartitionAsync(int partition)
            {
                throw new NotImplementedException();
            }

            public bool LocalPreloadPartition(int partition)
            {
                throw new NotImplementedException();
            }
        }
    }
}
