using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
 
using System.Web;
using System.Web.Caching;
using System.Web.SessionState;
using System.Web.UI;
namespace view.App_Code
{
    /// 
    /// When an ASP.NET State Server other than InProc, the Session_End event
    /// does not get fired.  This is an HttpModule which uses some workarounds
    /// and fires a static event when a session ends, with the value of a single
    /// configurable session variable in the event arguments.
    /// 
    public class SessionEndModule : IHttpModule
    {
        #region Private Variables
        private HttpApplication m_HttpApplication;
        private static string m_SessionObjectKey;
        #endregion
        #region Accessors
        /// 
        /// This is the key of the item in the session which should be returned
        /// in the SessionEnd event (as the SessionObject).
        /// 
        /// 
        ///	If you're storing the user ID in the session, under a key called 'UserId'
        /// and need to do something with it in the SessionEnd event, you would set
        /// this to 'UserId', which would cause the value of the session key called
        /// 'UserId' to be returned.
        /// 
        public static string SessionObjectKey
        {
            get
            {
                return m_SessionObjectKey;
            }
            set
            {
                m_SessionObjectKey = value;
            }
        }
        #endregion
        #region IHttpModule Implementation
        public void Init(HttpApplication context)
        {
            m_HttpApplication = context;
            m_HttpApplication.PreRequestHandlerExecute += new EventHandler(OnPreRequestHandlerExecute);
        }
        public void Dispose()
        {
            // Do Nothing
        }
        #endregion
        #region Events
        /// 
        /// Event raised when the session ends
        /// 
        public static event SessionEndEventHandler SessionEnd;
        #endregion
        private void OnPreRequestHandlerExecute(object sender, EventArgs e)
        {
            // We only want to update the session when an ASPX page is being viewed
            // We're also doing this in the PreRequestHandler, as doing it elsewhere
            // (like the PostRequestHandler) can cause some strange behaviour.
            if (Path.GetExtension(m_HttpApplication.Context.Request.Path).ToLower() == ".aspx")
            {
                // Ensure we have a HttpContext
                if (HttpContext.Current == null)
                {
                    Debug.WriteLine("No current http context");
                    return;
                }
                // Get the current session
                HttpSessionState currentSession = HttpContext.Current.Session;
                // Ensure we have a current session
                if (currentSession == null)
                {
                    Debug.WriteLine("No current session");
                    return;
                }
                // Get the session timeout
                TimeSpan sessionTimeout = new TimeSpan(0, 0, currentSession.Timeout, 0, 0);
                // Get the object in the session we want to retrieve when the session times out
                object sessionObject = currentSession[SessionObjectKey];
                // Add the object to the cache with the current session id, and set a cache removal callback method
                HttpContext.Current.Cache.Insert(currentSession.SessionID, sessionObject, null, DateTime.MaxValue, sessionTimeout, CacheItemPriority.NotRemovable, CacheItemRemovedCallbackMethod);
            }
        }
        /// 
        /// This method is fired when an item is removed from the cache.  It is used to detect when a cache item
        /// expires, indicating that the session has expired, and fires the SessionEnd event.
        /// 
        private void CacheItemRemovedCallbackMethod(string key, object value, CacheItemRemovedReason reason)
        {
            if (reason == CacheItemRemovedReason.Expired)
            {
                if (SessionEnd != null)
                {
                     SessionEndedEventArgs e = new SessionEndedEventArgs(key, value);
                     SessionEnd(this, e);
                     
                }
            }
        }
    }
    /// 
    /// Event handler for handling the SessionEnd event
    /// 
    public delegate void SessionEndEventHandler(object sender, SessionEndedEventArgs e);
    /// 
    /// SessionEndedEventArgs for use in the SessionEnd event
    /// 
    public class SessionEndedEventArgs : EventArgs
    {
        public readonly string SessionId;
        public readonly object SessionObject;
        public SessionEndedEventArgs(string sessionId, object sessionObject)
        {   
            SessionId = sessionId;
            SessionObject = sessionObject;
        }
    }
}