﻿/*
 * 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.AspNet
{
    using System;
    using System.Collections.Specialized;
    using System.Diagnostics;
    using System.Diagnostics.CodeAnalysis;
    using System.Globalization;
    using System.Threading;
    using System.Web;
    using System.Web.SessionState;
    using Apache.Ignite.AspNet.Impl;
    using Apache.Ignite.Core;
    using Apache.Ignite.Core.Binary;
    using Apache.Ignite.Core.Cache;
    using Apache.Ignite.Core.Common;
    using Apache.Ignite.Core.Impl.Cache;

    /// <summary>
    /// ASP.NET Session-State Store Provider that uses Ignite distributed cache as an underlying storage.
    /// <para />
    /// You can either start Ignite yourself, and provide <c>gridName</c> attribute, 
    /// or provide <c>igniteConfigurationSectionName</c> attribute to start Ignite automatically from specified
    /// configuration section (see <see cref="IgniteConfigurationSection"/>) 
    /// using <c>igniteConfigurationSectionName</c>.
    /// <para />
    /// <c>cacheName</c> attribute specifies Ignite cache name to use for data storage. This attribute can be omitted 
    /// if cache name is null.
    /// <para />
    /// Optional <c>applicationId</c> attribute allows sharing a single Ignite cache between multiple web applications.
    /// </summary>
    public class IgniteSessionStateStoreProvider : SessionStateStoreProviderBase
    {
        /// <summary>
        /// The default cache name to be used when <c>cacheName</c> attribute is not specified.
        /// </summary>
        public const string DefaultCacheName = "ASPNET_SESSION_STATE";

        /** Extension id  */
        private const int ExtensionId = 0;

        /// <summary>
        /// Op codes for <see cref="ICacheInternal.DoOutInOpExtension{T}"/>.
        /// </summary>
        private enum Op
        {
            /** Lock the session data. */
            Lock = 1,

            /** Update and unlock the session data. */
            SetAndUnlock = 2,

            /** Get the data without lock. */
            Get = 3,

            /** Put the data without lock. */
            Put = 4,

            /** Remove the data without lock. */
            Remove = 5
        }

        /** Application id config parameter. */
        private const string ApplicationId = "applicationId";

        /** */
        private volatile string _applicationId;

        /** */
        private volatile ExpiryCacheHolder<string, IgniteSessionStateStoreData> _expiryCacheHolder;

        /** */
        private static long _lockId;

        /// <summary>
        /// Initializes the provider.
        /// </summary>
        /// <param name="name">The friendly name of the provider.</param>
        /// <param name="config">A collection of the name/value pairs representing the provider-specific attributes 
        /// specified in the configuration for this provider.</param>
        [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods")]
        public override void Initialize(string name, NameValueCollection config)
        {
            base.Initialize(name, config);

            var cache = ConfigUtil.InitializeCache<string, IgniteSessionStateStoreData>(config, GetType(), 
                DefaultCacheName);

            _expiryCacheHolder = new ExpiryCacheHolder<string, IgniteSessionStateStoreData>(cache);

            _applicationId = config[ApplicationId];
        }


        /// <summary>
        /// Releases all resources used by the <see cref="System.Web.SessionState.SessionStateStoreProviderBase" /> 
        /// implementation.
        /// </summary>
        public override void Dispose()
        {
            // No-op.
        }

        /// <summary>
        /// Sets a reference to the <see cref="System.Web.SessionState.SessionStateItemExpireCallback" />
        /// delegate for the Session_OnEnd event defined in the Global.asax file.
        /// </summary>
        /// <param name="expireCallback">The <see cref="System.Web.SessionState.SessionStateItemExpireCallback" />
        /// delegate for the Session_OnEnd event defined in the Global.asax file.</param>
        /// <returns>
        /// true if the session-state store provider supports calling the Session_OnEnd event; otherwise, false.
        /// </returns>
        public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback)
        {
            // Expiration events not supported for now.
            return false;
        }

        /// <summary>
        /// Called by the <see cref="System.Web.SessionState.SessionStateModule" /> object 
        /// for per-request initialization.
        /// </summary>
        /// <param name="context">The <see cref="System.Web.HttpContext" /> for the current request.</param>
        public override void InitializeRequest(HttpContext context)
        {
            // No-op.
        }

        /// <summary>
        /// Returns read-only session-state data from the session data store.
        /// </summary>
        /// <param name="context">The <see cref="System.Web.HttpContext" /> for the current request.</param>
        /// <param name="id">The <see cref="System.Web.SessionState.HttpSessionState.SessionID" /> for the
        /// current request.</param>
        /// <param name="locked">When this method returns, contains a Boolean value that is set to true if the 
        /// requested session item is locked at the session data store; otherwise, false.</param>
        /// <param name="lockAge">When this method returns, contains a <see cref="System.TimeSpan" /> object that 
        /// is set to the amount of time that an item in the session data store has been locked.</param>
        /// <param name="lockId">When this method returns, contains an object that is set to the lock identifier 
        /// for the current request. For details on the lock identifier, see "Locking Session-Store Data" 
        /// in the <see cref="System.Web.SessionState.SessionStateStoreProviderBase" /> class summary.</param>
        /// <param name="actions">When this method returns, contains one of the 
        /// <see cref="System.Web.SessionState.SessionStateActions" /> values, indicating whether the current 
        /// session is an uninitialized, cookieless session.</param>
        /// <returns>
        /// A <see cref="System.Web.SessionState.SessionStateStoreData" /> populated with session values and 
        /// information from the session data store.
        /// </returns>
        public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked,
            out TimeSpan lockAge, out object lockId,
            out SessionStateActions actions)
        {
            actions = SessionStateActions.None;
            lockId = null;
            lockAge = TimeSpan.Zero;
            locked = false;

            var key = GetKey(id);
            var data = GetItem(key);

            if (data != null)
            {
                locked = data.LockNodeId != null;

                if (!locked)
                {
                    return data;
                }

                Debug.Assert(data.LockTime != null);

                lockAge = DateTime.UtcNow - data.LockTime.Value;

                lockId = data.LockId;

                return null;
            }

            return null;
        }

        /// <summary>
        /// Returns read-only session-state data from the session data store.
        /// </summary>
        /// <param name="context">The <see cref="System.Web.HttpContext" /> for the current request.</param>
        /// <param name="id">The <see cref="System.Web.SessionState.HttpSessionState.SessionID" /> for the current
        /// request.</param>
        /// <param name="locked">When this method returns, contains a Boolean value that is set to true if a lock 
        /// is successfully obtained; otherwise, false.</param>
        /// <param name="lockAge">When this method returns, contains a <see cref="System.TimeSpan" /> object that 
        /// is set to the amount of time that an item in the session data store has been locked.</param>
        /// <param name="lockId">When this method returns, contains an object that is set to the lock identifier 
        /// for the current request. For details on the lock identifier, see "Locking Session-Store Data" in 
        /// the <see cref="System.Web.SessionState.SessionStateStoreProviderBase" /> class summary.</param>
        /// <param name="actions">When this method returns, contains one of the 
        /// <see cref="System.Web.SessionState.SessionStateActions" /> values, indicating whether the current 
        /// session is an uninitialized, cookieless session.</param>
        /// <returns>
        /// A <see cref="System.Web.SessionState.SessionStateStoreData" /> populated with session values 
        /// and information from the session data store.
        /// </returns>
        public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked,
            out TimeSpan lockAge,
            out object lockId, out SessionStateActions actions)
        {
            actions = SessionStateActions.None;  // Our items never need initialization.
            lockAge = TimeSpan.Zero;
            lockId = null;

            var lockId0 = Interlocked.Increment(ref _lockId);

            var key = GetKey(id);

            var lockResult = LockItem(key, lockId0);

            // No item found.
            if (lockResult == null)
            {
                locked = false;

                return null;
            }

            // Item was already locked.
            if (!lockResult.Success)
            {
                locked = true;

                Debug.Assert(lockResult.LockTime != null);

                lockAge = DateTime.UtcNow - lockResult.LockTime.Value;
                lockId = lockResult.LockId;

                return null;
            }

            // Item found and lock obtained.
            locked = false;
            lockId = lockId0;

            if (lockId0 != lockResult.Data.LockId)
                throw new IgniteException(string.Format(CultureInfo.InvariantCulture, 
                    "Invalid session state lock result, " +
                    "expected lockId: {0}, actual: {1}", lockId0, lockResult.Data.LockId));

            return lockResult.Data;
        }

        /// <summary>
        /// Releases a lock on an item in the session data store.
        /// </summary>
        /// <param name="context">The <see cref="System.Web.HttpContext" /> for the current request.</param>
        /// <param name="id">The session identifier for the current request.</param>
        /// <param name="lockId">The lock identifier for the current request.</param>
        public override void ReleaseItemExclusive(HttpContext context, string id, object lockId)
        {
            UnlockItem(GetKey(id), (long) lockId);
        }

        /// <summary>
        /// Updates the session-item information in the session-state data store with values from the current request, 
        /// and clears the lock on the data.
        /// </summary>
        /// <param name="context">The <see cref="System.Web.HttpContext" /> for the current request.</param>
        /// <param name="id">The session identifier for the current request.</param>
        /// <param name="item">The <see cref="System.Web.SessionState.SessionStateStoreData" /> object that 
        /// contains the current session values to be stored.</param>
        /// <param name="lockId">The lock identifier for the current request.</param>
        /// <param name="newItem">true to identify the session item as a new item; false to identify the session 
        /// item as an existing item.</param>
        [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods")]
        public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item,
            object lockId, bool newItem)
        {
            Debug.Assert(item != null);

            var key = GetKey(id);

            var data = (IgniteSessionStateStoreData) item;

            if (newItem)
            {
                var cache = _expiryCacheHolder.GetCacheWithExpiry(data.Timeout * 60);

                PutItem(key, data, cache);
            }
            else
            {
                if (!(lockId is long) || data.LockId != (long) lockId)
                    throw new IgniteException(string.Format(CultureInfo.InvariantCulture,
                        "Invalid session release request, expected lockId: {0}, actual: {1}", data.LockId, lockId));

                SetAndUnlockItem(key, data);
            }
        }

        /// <summary>
        /// Deletes item data from the session data store.
        /// </summary>
        /// <param name="context">The <see cref="System.Web.HttpContext" /> for the current request.</param>
        /// <param name="id">The session identifier for the current request.</param>
        /// <param name="lockId">The lock identifier for the current request.</param>
        /// <param name="item">The <see cref="System.Web.SessionState.SessionStateStoreData" /> that represents 
        /// the item to delete from the data store.</param>
        public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item)
        {
            RemoveItem(GetKey(id));
        }

        /// <summary>
        /// Updates the expiration date and time of an item in the session data store.
        /// </summary>
        /// <param name="context">The <see cref="System.Web.HttpContext" /> for the current request.</param>
        /// <param name="id">The session identifier for the current request.</param>
        public override void ResetItemTimeout(HttpContext context, string id)
        {
            // No-op.

            // This is not necessary since ResetItemTimeout is called right after SetAndReleaseItemExclusive,
            // which itself resets the timeout when the item is inserted into cache.
        }

        /// <summary>
        /// Creates a new <see cref="System.Web.SessionState.SessionStateStoreData" /> object to be used 
        /// for the current request.
        /// </summary>
        /// <param name="context">The <see cref="System.Web.HttpContext" /> for the current request.</param>
        /// <param name="timeout">The session-state <see cref="System.Web.SessionState.HttpSessionState.Timeout" />
        /// value for the new <see cref="System.Web.SessionState.SessionStateStoreData" />, in minutes.</param>
        /// <returns>
        /// A new <see cref="System.Web.SessionState.SessionStateStoreData" /> for the current request.
        /// </returns>
        public override SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout)
        {
            return new IgniteSessionStateStoreData(SessionStateUtility.GetSessionStaticObjects(context), timeout);
        }

        /// <summary>
        /// Adds a new session-state item to the data store.
        /// </summary>
        /// <param name="context">The <see cref="System.Web.HttpContext" /> for the current request.</param>
        /// <param name="id">The <see cref="System.Web.SessionState.HttpSessionState.SessionID" />
        /// for the current request.</param>
        /// <param name="timeout">The session <see cref="System.Web.SessionState.HttpSessionState.Timeout" />
        /// for the current request, in minutes.</param>
        public override void CreateUninitializedItem(HttpContext context, string id, int timeout)
        {
            var cache = _expiryCacheHolder.GetCacheWithExpiry((long) timeout * 60);

            var key = GetKey(id);

            var data = new IgniteSessionStateStoreData(SessionStateUtility.GetSessionStaticObjects(context), timeout);

            PutItem(key, data, cache);
        }

        /// <summary>
        /// Called by the <see cref="System.Web.SessionState.SessionStateModule" /> object at the end of a request.
        /// </summary>
        /// <param name="context">The <see cref="System.Web.HttpContext" /> for the current request.</param>
        public override void EndRequest(HttpContext context)
        {
            // No-op.
        }

        /// <summary>
        /// Gets the cache.
        /// </summary>
        private ICache<string, IgniteSessionStateStoreData> Cache
        {
            get
            {
                var holder = _expiryCacheHolder;

                if (holder == null)
                    throw new InvalidOperationException(GetType() + " has not been initialized.");

                return holder.Cache;
            }
        }

        /// <summary>
        /// Gets the key.
        /// </summary>
        private string GetKey(string sessionId)
        {
            return _applicationId == null ? sessionId : ApplicationId + "." + sessionId;
        }

        /// <summary>
        /// Writes the lock info.
        /// </summary>
        private void WriteLockInfo(IBinaryRawWriter writer, long lockId, bool writeTime = false)
        {
            writer.WriteGuid(Cache.Ignite.GetCluster().GetLocalNode().Id);
            writer.WriteLong(lockId);

            if (writeTime)
                writer.WriteTimestamp(DateTime.UtcNow);
        }

        /// <summary>
        /// Locks the item.
        /// </summary>
        private SessionStateLockResult LockItem(string key, long lockId)
        {
            return OutInOp(Op.Lock,
                w =>
                {
                    w.WriteString(key);
                    WriteLockInfo(w, lockId, true);
                }, 
                r => new SessionStateLockResult(r));
        }

        /// <summary>
        /// Unlocks the item.
        /// </summary>
        private void UnlockItem(string key, long lockId)
        {
            OutOp(Op.SetAndUnlock,
                w =>
                {
                    w.WriteString(key);
                    w.WriteBoolean(false); // Only unlock.
                    WriteLockInfo(w, lockId);
                });
        }

        /// <summary>
        /// Sets and unlocks the item.
        /// </summary>
        private void SetAndUnlockItem(string key, IgniteSessionStateStoreData data)
        {
            var cache = _expiryCacheHolder.GetCacheWithExpiry(data.Timeout * 60);

            OutOp(Op.SetAndUnlock, w =>
            {
                w.WriteString(key);
                w.WriteBoolean(true); // Unlock and update.
                data.WriteBinary(w, true);
            }, cache);
        }

        /// <summary>
        /// Puts the item.
        /// </summary>
        private void PutItem(string key, IgniteSessionStateStoreData data, ICache<string, IgniteSessionStateStoreData> cache)
        {
            OutOp(Op.Put, w =>
            {
                w.WriteString(key);
                data.WriteBinary(w, false);
            }, cache);
        }

        /// <summary>
        /// Gets the item.
        /// </summary>
        private IgniteSessionStateStoreData GetItem(string key)
        {
            return OutInOp(Op.Get, w => w.WriteString(key), r => new IgniteSessionStateStoreData(r));
        }

        /// <summary>
        /// Removes the item.
        /// </summary>
        private void RemoveItem(string key)
        {
            OutOp(Op.Remove, w => w.WriteString(key));
        }

        /// <summary>
        /// Invokes the extension operation.
        /// </summary>
        private void OutOp(Op op, Action<IBinaryRawWriter> writeAction, 
            ICache<string, IgniteSessionStateStoreData> cache = null)
        {
            OutInOp<object>(op, writeAction, null, cache);
        }

        /// <summary>
        /// Invokes the extension operation.
        /// </summary>
        private T OutInOp<T>(Op op, Action<IBinaryRawWriter> writeAction, Func<IBinaryRawReader, T> readFunc, 
            ICache<string, IgniteSessionStateStoreData> cache = null)
        {
            cache = cache ?? Cache;

            return ((ICacheInternal) cache).DoOutInOpExtension(ExtensionId, (int) op, writeAction, readFunc);
        }
    }
}
