using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace DevComponents.DotNetBar
{
    /// 
    /// Class that tracks lists of all controls that host currently open popups.
    /// 
    public static class PopupManager
    {
        #region Constructor
        private static List _RegisteredPopups = new List();
        private static ReaderWriterLock ReadWritePopupsListLock;
        static PopupManager()
        {
            PopupManager.ReadWritePopupsListLock = new ReaderWriterLock();
        }
        #endregion
        #region Implementation
        /// 
        /// Registers IOwnerMenuSupport popup host in response to host displaying its first popup.
        /// 
        /// IOwnerMenuSupport host to register
        public static void RegisterPopup(IOwnerMenuSupport popupHost)
        {
            if (popupHost == null) return;
            if (GetHostReference(popupHost) == null)
            {
                WeakReference reference = new WeakReference(popupHost);
                reference.Target = popupHost;
                LockCookie cookie1 = new LockCookie();
                bool readerLockHeld = PopupManager.ReadWritePopupsListLock.IsReaderLockHeld;
                if (readerLockHeld)
                {
                    cookie1 = PopupManager.ReadWritePopupsListLock.UpgradeToWriterLock(-1);
                }
                else
                {
                    PopupManager.ReadWritePopupsListLock.AcquireWriterLock(-1);
                }
                try
                {
                    _RegisteredPopups.Add(reference);
                }
                finally
                {
                    if (readerLockHeld)
                    {
                        PopupManager.ReadWritePopupsListLock.DowngradeFromWriterLock(ref cookie1);
                    }
                    else
                    {
                        PopupManager.ReadWritePopupsListLock.ReleaseWriterLock();
                    }
                }
                popupHost = null;
            }
        }
        private static WeakReference GetHostReference(IOwnerMenuSupport host)
        {
            List registeredControls = _RegisteredPopups;
            if (registeredControls == null) return null;
            PopupManager.ReadWritePopupsListLock.AcquireReaderLock(-1);
            try
            {
                foreach (WeakReference item in registeredControls)
                {
                    object target = item.Target;
                    if (target != null && target.Equals(host))
                        return item;
                }
            }
            finally
            {
                PopupManager.ReadWritePopupsListLock.ReleaseReaderLock();
            }
            return null;
        }
        /// 
        /// Unregisters IOwnerMenuSupport popup host in response to host closing its last popup.
        /// 
        /// IOwnerMenuSupport host to unregister
        public static void UnregisterPopup(IOwnerMenuSupport popupHost)
        {
            if (popupHost == null) return;
            LockCookie cookie1 = new LockCookie();
            bool readerLockHeld = PopupManager.ReadWritePopupsListLock.IsReaderLockHeld;
            if (readerLockHeld)
            {
                cookie1 = PopupManager.ReadWritePopupsListLock.UpgradeToWriterLock(-1);
            }
            else
            {
                PopupManager.ReadWritePopupsListLock.AcquireWriterLock(-1);
            }
            try
            {
                foreach (WeakReference item in _RegisteredPopups)
                {
                    object target = item.Target;
                    if (target != null && target.Equals(popupHost))
                    {
                        _RegisteredPopups.Remove(item);
                        break;
                    }
                }
            }
            finally
            {
                if (readerLockHeld)
                {
                    PopupManager.ReadWritePopupsListLock.DowngradeFromWriterLock(ref cookie1);
                }
                else
                {
                    PopupManager.ReadWritePopupsListLock.ReleaseWriterLock();
                }
            }
        }
        /// 
        /// Closes all currently open popups.
        /// 
        public static void CloseAllPopups()
        {
            CloseAllPopups(null);
        }
        /// 
        /// Closes all currently open popups excluding specified popup host.
        /// 
        /// IOwnerMenuSupport host to exclude from closing or null
        public static void CloseAllPopups(IOwnerMenuSupport excludeHost)
        {
            WeakReference[] references;
            PopupManager.ReadWritePopupsListLock.AcquireReaderLock(-1);
            try
            {
                references = new WeakReference[_RegisteredPopups.Count];
                _RegisteredPopups.CopyTo(references);
            }
            finally
            {
                PopupManager.ReadWritePopupsListLock.ReleaseReaderLock();
            }
            foreach (WeakReference reference in references)
            {
                object target = reference.Target;
                if (reference.IsAlive)
                {
                    if (target != null)
                    {
                        IOwnerMenuSupport popupHost = target as IOwnerMenuSupport;
                        if (popupHost != null && popupHost != excludeHost)
                        {
                            popupHost.ClosePopups();
                        }
                    }
                }
            }
        }
        #endregion
    }
}