/*
 * 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.
 */

namespace Apache.Ignite.Core.Tests.Cache.Store
{
    using System;
    using System.Collections.Concurrent;
    using System.Collections.Generic;
    using System.Linq;
    using Apache.Ignite.Core.Cache.Store;
    using Apache.Ignite.Core.Resource;
    using NUnit.Framework;

    /// <summary>
    /// Tests for store session.
    /// </summary>
    public class CacheStoreSessionTest
    {
        /** Cache 1 name. */
        protected const string Cache1 = "cache1";

        /** Cache 2 name. */
        protected const string Cache2 = "cache2";

        /** Operations. */
        private static ConcurrentBag<ICollection<Operation>> _dumps;

        /// <summary>
        /// Set up routine.
        /// </summary>
        [TestFixtureSetUp]
        public void BeforeTests()
        {
            Ignition.Start(GetIgniteConfiguration());
        }

        /// <summary>
        /// Gets the ignite configuration.
        /// </summary>
        protected virtual IgniteConfiguration GetIgniteConfiguration()
        {
            return new IgniteConfiguration(TestUtils.GetTestConfiguration())
            {
                SpringConfigUrl = @"Config/Cache/Store/cache-store-session.xml"
            };
        }

        /// <summary>
        /// Gets the store count.
        /// </summary>
        protected virtual int StoreCount
        {
            get { return 2; }
        }

        /// <summary>
        /// Tear down routine.
        /// </summary>
        [TestFixtureTearDown]
        public void AfterTests()
        {
            try
            {
                TestUtils.AssertHandleRegistryHasItems(Ignition.GetIgnite(), 2, 1000);
            }
            finally
            {
                Ignition.StopAll(true);
            }
        }

        /// <summary>
        /// Test basic session API.
        /// </summary>
        [Test]
        [Timeout(30000)]
        public void TestSession()
        {
            _dumps = new ConcurrentBag<ICollection<Operation>>();

            var ignite = Ignition.GetIgnite();

            var cache1 = ignite.GetCache<int, int>(Cache1);
            var cache2 = ignite.GetCache<int, int>(Cache2);

            // 1. Test rollback.
            using (var tx = ignite.GetTransactions().TxStart())
            {
                cache1.Put(1, 1);
                cache2.Put(2, 2);

                tx.Rollback();
            }

            // SessionEnd should not be called.
            Assert.AreEqual(0, _dumps.Count);

            // 2. Test puts.
            using (var tx = ignite.GetTransactions().TxStart())
            {
                cache1.Put(1, 1);
                cache2.Put(2, 2);

                tx.Commit();
            }

            Assert.AreEqual(StoreCount, _dumps.Count);

            foreach (var ops in _dumps)
            {
                Assert.AreEqual(2 + StoreCount, ops.Count);
                Assert.AreEqual(1, ops.Count(op => op.Type == OperationType.Write
                                                   && Cache1 == op.CacheName && 1 == op.Key && 1 == op.Value));
                Assert.AreEqual(1, ops.Count(op => op.Type == OperationType.Write
                                                   && Cache2 == op.CacheName && 2 == op.Key && 2 == op.Value));
                Assert.AreEqual(StoreCount, ops.Count(op => op.Type == OperationType.SesEnd && op.Commit));
            }

            _dumps = new ConcurrentBag<ICollection<Operation>>();

            // 3. Test removes.
            using (var tx = ignite.GetTransactions().TxStart())
            {
                cache1.Remove(1);
                cache2.Remove(2);

                tx.Commit();
            }

            Assert.AreEqual(StoreCount, _dumps.Count);
            foreach (var ops in _dumps)
            {
                Assert.AreEqual(2 + StoreCount, ops.Count);

                Assert.AreEqual(1, ops.Count(op => op.Type == OperationType.Delete
                                                   && Cache1 == op.CacheName && 1 == op.Key));
                Assert.AreEqual(1, ops.Count(op => op.Type == OperationType.Delete
                                                   && Cache2 == op.CacheName && 2 == op.Key));
                Assert.AreEqual(StoreCount, ops.Count(op => op.Type == OperationType.SesEnd && op.Commit));
            }
        }

        /// <summary>
        /// Dump operations.
        /// </summary>
        /// <param name="dump">Dump.</param>
        private static void DumpOperations(ICollection<Operation> dump)
        {
            _dumps.Add(dump);
        }

        /// <summary>
        /// Test store implementation.
        /// </summary>
        // ReSharper disable once UnusedMember.Global
        public class Store : CacheStoreAdapter<object, object>
        {
            /** Store session. */
            [StoreSessionResource]
#pragma warning disable 649
            private ICacheStoreSession _ses;
#pragma warning restore 649

            /** <inheritdoc /> */
            public override object Load(object key)
            {
                throw new NotImplementedException();
            }

            /** <inheritdoc /> */
            public override void Write(object key, object val)
            {
                GetOperations().Add(new Operation(_ses.CacheName, OperationType.Write, (int)key, (int)val));
            }

            /** <inheritdoc /> */
            public override void Delete(object key)
            {
                GetOperations().Add(new Operation(_ses.CacheName, OperationType.Delete, (int)key, 0));
            }

            /** <inheritdoc /> */
            public override void SessionEnd(bool commit)
            {
                Operation op = new Operation(_ses.CacheName, OperationType.SesEnd) { Commit = commit };

                ICollection<Operation> ops = GetOperations();

                ops.Add(op);

                DumpOperations(ops);
            }

            /// <summary>
            /// Get collection with operations.
            /// </summary>
            /// <returns>Operations.</returns>
            private ICollection<Operation> GetOperations()
            {
                object ops;

                if (!_ses.Properties.TryGetValue("ops", out ops))
                {
                    ops = new List<Operation>();

                    _ses.Properties["ops"] = ops;
                }

                return (ICollection<Operation>) ops;
            }
        }

        /// <summary>
        /// Logged operation.
        /// </summary>
        private class Operation
        {
            /// <summary>
            /// Constructor.
            /// </summary>
            /// <param name="cacheName">Cache name.</param>
            /// <param name="type">Operation type.</param>
            public Operation(string cacheName, OperationType type)
            {
                CacheName = cacheName;
                Type = type;
            }

            /// <summary>
            /// Constructor.
            /// </summary>
            /// <param name="cacheName">Cache name.</param>
            /// <param name="type">Operation type.</param>
            /// <param name="key">Key.</param>
            /// <param name="val">Value.</param>
            public Operation(string cacheName, OperationType type, int key, int val) : this(cacheName, type)
            {
                Key = key;
                Value = val;
            }

            /// <summary>
            /// Cache name.
            /// </summary>
            public string CacheName { get; private set; }

            /// <summary>
            /// Operation type.
            /// </summary>
            public OperationType Type { get; private set; }

            /// <summary>
            /// Key.
            /// </summary>
            public int Key { get; private set; }

            /// <summary>
            /// Value.
            /// </summary>
            public int Value { get; private set; }

            /// <summary>
            /// Commit flag.
            /// </summary>
            public bool Commit { get; set; }
        }

        /// <summary>
        /// Operation types.
        /// </summary>
        private enum OperationType
        {
            /** Write. */
            Write,

            /** Delete. */
            Delete,

            /** Session end. */
            SesEnd
        }
    }
}
