#region  --------------- Copyright Dresser Wayne Pignone -------------
/*
 * $Log: /Wrk/WayneLibraries/Wrk/StateEngine/Timer.cs $
 * 
 * 4     08-03-18 11:09 roger.m�nsson
 * Each timer does not have it's own real timer anymore. Instead there are
 * a pool of timers in the StateMachine that can be shared among the
 * timers in the same state machine.
 * 
 * 3     08-02-26 14:11 Mattias.larsson
 * Removed Obsolete method.
 */
#endregion
#region Old file header
/*===============================================================================
 * Timer
 * 
 * Change history
 * When         Who     Comment
 * ----------   ------  ------------------------------------
 * 2006-06-17   RMa     Added userToken to the timer and timer event.
 * 2006-05-09   RMa     Improved dispose handling.
 * 2006-03-02   RMa     FXCop updates: Implement IDisposable.
 * 2005-12-09   RMa     Improved the Disable functionality.
 * 2005-12-05   RMa     This header added.
 * 
---------------------------------------------------------------------------------*/

#endregion

using System;
namespace Wayne.Lib.StateEngine
{
    /// <summary>
    /// Delegate that is used to signal to the state machine that the timer event has timed out.
    /// </summary>
    /// <param name="elapsedTimer"></param>
    internal delegate void TimerElapsedDelegate(Timer elapsedTimer);

    /// <summary>
    /// Timer is a timer that should be used within the state machine. 
    /// </summary>
    public class Timer : IDisposable
    {
        #region Fields

        private bool isPeriodic;
        private bool clearAtStateExit = true;
        private object eventType;
        private State ownerState;
        private int interval;
        private object userToken;
        private bool enabled;
        private int idx = nextIdx++;


        //public int Idx
        //{
        //    get { return idx; }
        //    set { idx = value; }
        //}

        #endregion

        #region Static Fiedls
        static int nextIdx;
        #endregion


        #region Events

        internal event EventHandler OnEnable;
        internal event EventHandler OnDisable;

        #endregion

        #region Construction

        /// <summary>
        /// Constructor for Timer
        /// </summary>
        /// <param name="ownerState">State that created the timer</param>
        /// <param name="eventType">Type that should be set in the timer event that is sent when the timer fires</param>
        /// <param name="interval">Interval of the timer</param>
        /// <param name="userToken">Token object that is supplied by the user and that is returned in the TimerEvent.</param>
        public Timer(State ownerState, object eventType, int interval, object userToken)
        {
            this.ownerState = ownerState;
            this.eventType = eventType;
            this.interval = interval;
            this.userToken = userToken;
        }

        /// <summary>
        /// Finalizer
        /// </summary>
        ~Timer()
        {
            Dispose(false);
        }

        #endregion

        #region Properties

        /// <summary>
        /// Specifies if the timer should fire several times.
        /// </summary>
        public bool IsPeriodic
        {
            get { return isPeriodic; }
            set { isPeriodic = value; }
        }

        /// <summary>
        /// Specifies if the timer should be disabled automatically when the owning state is exit.
        /// </summary>
        public bool ClearAtStateExit
        {
            get { return clearAtStateExit; }
            set { clearAtStateExit = value; }
        }

        /// <summary>
        /// State object that created the timer.
        /// </summary>
        public State OwnerState
        {
            get { return ownerState; }
            set { ownerState = value; }
        }

        /// <summary>
        /// Event type that should be set in the TimerEvent when it fires.
        /// </summary>
        public object EventType
        {
            get { return eventType; }
            set { eventType = value; }
        }

        /// <summary>
        /// If the timer is active.
        /// </summary>
        public bool Enabled
        {
            get { return enabled; }
        }

        /// <summary>
        /// User-supplied token that is sent in to the constructor at creation time.
        /// </summary>
        public object UserToken
        {
            get { return userToken; }
        }

        /// <summary>
        /// The interval of the timer.
        /// </summary>
        public int Interval
        {
            get { return interval; }
            set { interval = value; }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Enables the timer
        /// </summary>
        public void Enable()
        {
            enabled = true;
            if (OnEnable != null)
                OnEnable(this, EventArgs.Empty);
        }

        /// <summary>
        /// Disables the timer.
        /// </summary>
        public void Disable()
        {
            enabled = false;
            if (OnDisable != null)
                OnDisable(this, EventArgs.Empty);
        }



        #endregion

        #region IDisposable Members

        /// <summary>
        /// Dispose disables the timer.
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool disposing)
        {
            if (enabled)
                Disable(); //Disable the timer.

            if (disposing)
            {
                //Nothing to dispose.
            }
        }

        #endregion

        #region ToString 

        /// <summary>
        /// ToString method.
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return string.Format(System.Globalization.CultureInfo.InvariantCulture, "Timer State={0}, Idx={1}, Interval={2}, IsPeriodic={3}", ownerState.LogName, idx, interval, IsPeriodic);
        }

        #endregion 
    }
}