// $Id$
// 
// Copyright 2007-2008 Cisco Systems Inc.
// 
// Licensed 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.

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;

namespace Etch.Util
{
    
    /// <summary>
    /// The alarm manager is used to implement alarms.
    /// A listener desiring a wakeup call should add itself to the manager
    /// with the specified delay in milliseconds. The listener may be removed
    /// at any time. When the alarm goes off, the listener may reset or remove
    /// the alarm.
    /// </summary>
    public class AlarmManager : AbstractStartable
    {
        /// <summary>
        /// Adds the listener to the set of those getting wakeup calls.
        /// </summary>
        /// <param name="listener">the target of the wakeup call.</param>
        /// <param name="state">a bit of state for the listener.</param>
        /// <param name="delay">the positive delay in milliseconds before the wakeup call.</param>
        public static void staticAdd(AlarmListener listener, Object state, int delay)
        {
            GetAlarmManager(true).Add(listener, state, delay);
        }

        /// <summary>
        /// Removes the listener from the set of those getting wakeup calls.
        /// </summary>
        /// <param name="listener">the target of the wakeup call.</param>
        public static void staticRemove(AlarmListener listener)
        {
            AlarmManager am = GetAlarmManager(false);
            if (am != null)
                am.Remove(listener);
        }

        /// <summary>
        /// Gets the statically configured alarm manager, creating one if
        /// specified and none exists.
        /// </summary>
        /// <param name="startIt">if true, we really need one and if there isn't
        /// one then one should be started, otherwise one should not be started</param>
        /// <returns>he statically configured alarm manager, or a newly
        /// created one if there is none.</returns>
        public static AlarmManager GetAlarmManager(bool startIt)
        {
            if (alarmManager == null)
            {
                lock (alarmManagerSync)
                {
                    if (alarmManager == null)
                    {
                        if (!startIt)
                            return null;

                        AlarmManager am = new AlarmManager();
                        am.Start();
                        alarmManager = am;
                    }
                }
            }

            return alarmManager;
        }

        /// <summary>
        /// Sets the statically configured alarm manager, returning the old one
        /// if any. Don't forget to stop the old one.
        /// </summary>
        /// <param name="newAlarmManager">a new AlarmManager to be statically available</param>
        /// <returns>the old statically available AlarmManager.</returns>
        public static AlarmManager SetAlarmManager(AlarmManager newAlarmManager)
        {
            lock (alarmManagerSync)
            {
                AlarmManager oldAlarmManager = alarmManager;
                alarmManager = newAlarmManager;
                return oldAlarmManager;
            }
        }

        private static AlarmManager alarmManager;

        private readonly static Object alarmManagerSync = new Object();

        /// <summary>
        /// Constructs the AlarmManager.
        /// </summary>
        /// <param name="nWorkers">the number of worker threads to create to process
        /// wakeups. Must be > 0 and < 100.</param>
        public AlarmManager(int nWorkers)
        {
            if (nWorkers <= 0 || nWorkers >= 100)
                throw new ArgumentException("nWorkers <= 0 || nWorkers >= 100");

            this.nWorkers = nWorkers;
        }

        /// <summary>
        /// onstructs the AlarmManager with the default number of workers.
        /// </summary>
        public AlarmManager()
            : this(DEFAULT_NWORKERS)
        {

        }

        private readonly int nWorkers;

        /// <summary>
        /// The default number of worker threads (1).
        /// </summary>
        public const int DEFAULT_NWORKERS = 1;


        protected override void Start0()
        {
            ClearAlarms();
            ClearQueue();

            worker = new Thread[nWorkers];
            for (int i = 0; i < nWorkers; i++)
            {
                worker[i] = new Thread(new ThreadStart(run));
                worker[i].IsBackground = true;
                worker[i].Start();
            }
        }
        private Thread[] worker;

        protected override void Stop0()
        {
            ClearAlarms();
            ClearQueue();
            System.Threading.Monitor.PulseAll(this);

            for (int i = 0; i < nWorkers; i++)
            {
                if (worker[i] != null)
                {
                    worker[i].Join();
                    worker[i] = null;
                }
            }
        }

        /// <summary>
        /// Adds the listener to the set of those getting wakeup calls. If the
        /// listener is already scheduled for a wakeup call, the schedule is
        /// adjusted. There can only be one outstanding wakeup call per listener.
        /// This method is thread safe.
        /// </summary>
        /// <param name="listener">the target of the wakeup call.</param>
        /// <param name="state">a bit of state for the listener.</param>
        /// <param name="delay">the positive delay in milliseconds before the wakeup call.</param>
        /// <exception cref="ArgumentException">throws ArgumentException if the delay is less
        /// than or equal to 0</exception>
        [MethodImpl(MethodImplOptions.Synchronized)]
        public void Add(AlarmListener listener, Object state, int delay)
        {
            if (listener == null)
                throw new NullReferenceException("listener == null");

            if (delay <= 0)
                throw new ArgumentException("delay <= 0");

            CheckIsStarted();

            long due = HPTimer.Now() + delay * HPTimer.NS_PER_MILLISECOND;

            Alarm alarm = GetAlarm(listener);
            if (alarm != null)
            {
                // schedule is being adjusted
                Dequeue(alarm);
                alarm.setDue(due);
                alarm.setState(state);
                Enqueue(alarm);
            }
            else
            {
                alarm = new Alarm(listener, state, due);
                AddAlarm(listener, alarm);
                Enqueue(alarm);
            }

            NotifyWorker("add");
        }

        [MethodImpl(MethodImplOptions.Synchronized)]
        private void Update(Alarm alarm, int delay)
        {
            long due = delay > 0
                ? alarm.getDue() + delay * HPTimer.NS_PER_MILLISECOND
                : HPTimer.Now() - delay * HPTimer.NS_PER_MILLISECOND;

            alarm.setDue(due);
            Enqueue(alarm);

            NotifyWorker("update");
        }

        /// <summary>
        /// Removes any scheduled wakeup call for this listener.
        /// This method is thread safe.
        /// </summary>
        /// <param name="listener">the target of the wakeup call.</param>
        [MethodImpl(MethodImplOptions.Synchronized)]
        public void Remove(AlarmListener listener)
        {
            CheckIsStarted();

            Alarm alarm = RemoveAlarm(listener);
            if (alarm != null)
                Dequeue(alarm);

            NotifyWorker("remove");
        }

        [MethodImpl(MethodImplOptions.Synchronized)]
        private void Remove(Alarm alarm)
        {
            RemoveAlarm(alarm.listener);
        }

        private void Wakeup(Alarm alarm)
        {
            try
            {
                int delay = alarm.listener.Wakeup(this, alarm.getState(), alarm.getDue());
                if (delay != 0)
                    Update(alarm, delay);
                else
                    Remove(alarm);
            }
            catch (Exception)
            {
                Remove(alarm);
                //			Log.report( "wakeup", "who", alarm.listener, Log.EXCP, e );
            }
        }

        private Alarm getNextDueAlarm()
        {
            // ok, the worker needs to get the next due alarm and
            // then wait until its due time, then return it. if alerted
            // by notifyWorker, it should refresh the next due alarm.
            // one trick will be in excluding multiple workers from
            // coming in here at the same time.
            lock (getNextDueAlarmSync)
            {
                lock (this)
                {
                    while (true)
                    {
                        //					
                        if (!IsStarted())
                            return null;

                        Alarm alarm = getFirst();

                        if (alarm == null)
                        {
                            try
                            {
                                //Console.WriteLine(" Waiting in getNextDueAlarm ");

                                System.Threading.Monitor.Wait(this, Int32.MaxValue);

                                //Console.WriteLine(" Done Waiting in getNextDueAlarm ");

                                continue;
                            }
                            catch (Exception e)
                            {
                                Console.WriteLine(e);
                                return null;
                            }
                        }

                        long delayNs = alarm.getDue() - HPTimer.Now();
                        if (delayNs > 0)
                        {
                            try
                            {
                                long delay = delayNs / HPTimer.NS_PER_MILLISECOND;
                                if (delay > 0)
                                {
                                    int d = (int)delay;
                                    System.Threading.Monitor.Wait(this, d);
                                }
                                continue;
                            }
                            catch (Exception e)
                            {
                                Console.WriteLine(e);
                                return null;
                            }
                        }

                        // the alarm being returned has not been removed
                        // from alarmsByListener. it is presumed that the
                        // alarm will be set again. if not, it should be
                        // removed.

                        Dequeue(alarm);
                        return alarm;
                    }
                }
            }
        }

        private readonly Object getNextDueAlarmSync = new Object();

        private void NotifyWorker(String reason)
        {
            //		Log.report( "notify", "who", this, "reason", reason, "where", new Throwable() );
            // the set of alarms has changed.
            System.Threading.Monitor.Pulse(this);
        }

        public void run()
        {
            try
            {
                Alarm alarm;
                while ((alarm = getNextDueAlarm()) != null)
                {
                    Wakeup(alarm);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }

        }

        private Alarm GetAlarm(AlarmListener listener)
        {
            Alarm alarm;
            return alarmsByListener.TryGetValue(listener, out alarm) ? alarm : null;
        }

        private void AddAlarm(AlarmListener listener, Alarm alarm)
        {
            alarmsByListener.Add(listener, alarm);
        }

        private Alarm RemoveAlarm(AlarmListener listener)
        {
            Alarm alarm = GetAlarm(listener);
            if (alarm != null)
                alarmsByListener.Remove(listener);
            return alarm;
        }

        private void ClearAlarms()
        {
            alarmsByListener.Clear();
        }

        private readonly Dictionary<AlarmListener, Alarm> alarmsByListener = new Dictionary<AlarmListener, Alarm>();

        ////////////////////////
        // ALARMS BY DUE TIME //
        ////////////////////////

        private Alarm getFirst()
        {
            if (alarms.Count == 0)
                return null;

            return alarms[0];
        }

        private void Enqueue(Alarm alarm)
        {
            alarms.Add(alarm);
            alarms.Sort();
        }

        private void Dequeue(Alarm alarm)
        {
            alarms.Remove(alarm);

        }

        private void ClearQueue()
        {
            alarms.Clear();
        }

        private readonly List<Alarm> alarms = new List<Alarm>();


        private class Alarm : IComparable<Alarm>
        {
            /// <summary>
            /// 
            /// </summary>
            /// <param name="listener">the target of the wakeup call.</param>
            /// <param name="state">a bit of state for the listener.</param>
            /// <param name="due">he absolute due time for the alarm.</param>
            public Alarm(AlarmListener listener, Object state, long due)
            {
                this.listener = listener;
                this.state = state;
                this.due = due;
            }

            /// <summary>
            /// 
            /// </summary>
            /// <returns>the state for the listener.</returns>
            public Object getState()
            {
                return state;
            }

            /// <summary>
            /// 
            /// </summary>
            /// <param name="state">a new bit of state for the listener./param>
            public void setState(Object state)
            {
                this.state = state;
            }

            /// <summary>
            /// 
            /// </summary>
            /// <returns>the time the alarm is due.</returns>
            public long getDue()
            {
                return due;
            }

            /// <summary>
            /// 
            /// </summary>
            /// <param name="due"></param>
            public void setDue(long due)
            {
                this.due = due;
            }


            public override int GetHashCode()
            {
                return (int)((due ^ (due >> 32)) ^ (seq ^ (seq >> 32)));
            }


            public override bool Equals(Object obj)
            {
                if (obj == this)
                    return true;



                if (obj == null)
                    return false;

                if (obj.GetType() != typeof(Alarm))
                    return false;

                Alarm other = (Alarm)obj;

                return due == other.due && seq == other.seq;
            }

            public int CompareTo(Alarm other)
            {
                if (due < other.due)
                    return -1;

                if (due > other.due)
                    return 1;

                // due time is the same for both, now we need to
                // compare the seq.

                if (seq < other.seq)
                    return -1;

                if (seq > other.seq)
                    return 1;

                return 0;
            }

            /// <summary>
            /// The listener for wakeup events.
            /// </summary>
            public readonly AlarmListener listener;

            /// <summary>
            /// Just a bit of state for the listener.
            /// </summary>
            private Object state;

            /// <summary>
            /// The time the alarm is due.
            /// </summary>
            private long due;

            /// <summary>
            /// A unique for all reasonable time sequence number.
            /// </summary>
            private readonly long seq = idGen.Next();

            private readonly static IdGenerator idGen = new IdGenerator();
        }

        /// <summary>
        /// Shuts down the default alarm manager if there is one.
        /// </summary>
        public static void shutdown()
        {
            AlarmManager am = SetAlarmManager(null);
            if (am != null)
                am.Stop();
        }



    }
}
