using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using MarketData.MarketDataModel;
using MarketData.DataAccess;
using MarketData.Utils;

namespace MarketData.Helper
{
  public class MarketDataHelperBase<T>
  {
    private List<T> queue=null;
    private int currentIndex=-1;
    public MarketDataHelperBase()
    {
    }
    public List<T> Queue
    {
      get{return queue;}
      set{queue=value;}
    }
    public void ShuffleQueue()
    {
      int itemCount = queue.Count;
      Random generator = new Random();
      for (int index = 0; index < itemCount; index++)
      {
        int r1;
        int r2;
        r1 = generator.Next(0, itemCount - 1);
        r2 = generator.Next(0, itemCount - 1);
        while (r2.Equals(r1)) r2 = generator.Next(0, itemCount - 1);
        T temp = queue[r1];
        queue[r1] = queue[r2];
        queue[r2] = temp;
      }
    }

    public T PeekQueueItem()
    {
      if(null==queue)return default(T);
      if (currentIndex+1 >= queue.Count) return default(T);
      return queue[currentIndex+1];
    }

    public T GetQueueItem()
    {
      if(null==queue)return default(T);
      if (currentIndex+1 >= queue.Count) return default(T);
      return queue[++currentIndex];
    }

    public int Index
    {
      get{return currentIndex;}
      set{currentIndex=value;}
    }

    public ManualResetEvent[] ResizeEvents(ManualResetEvent[] events)
    {
      ManualResetEvent[] busyEvents=GetBusyEvents(events);
      if(busyEvents.Length!=0)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Resizing event queue to {0}",busyEvents.Length));
        ManualResetEvent[] resizedEvents=new ManualResetEvent[busyEvents.Length];
        Array.Copy(busyEvents, resizedEvents, busyEvents.Length);
        return resizedEvents;
      }
      return events;
    }

    public ManualResetEvent[] GetBusyEvents(ManualResetEvent[] resetEvents)
    {
      List<ManualResetEvent> availableEvents = new List<ManualResetEvent>();
      for (int index = 0; index < resetEvents.Length; index++)
      {
        if (!resetEvents[index].WaitOne(0))
        {
          MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Event {0} is still doing work",resetEvents[index].SafeWaitHandle.DangerousGetHandle().ToString()));
          availableEvents.Add(resetEvents[index]);
        }
      }
      MDTrace.WriteLine(LogLevel.DEBUG,String.Format("The event queue has {0} busy slots",availableEvents.Count));
      return availableEvents.ToArray();
    }

    public ManualResetEvent[] GetAvailableEvents(ManualResetEvent[] resetEvents) 
    {
      List<ManualResetEvent> availableEvents = new List<ManualResetEvent>();
      for (int index = 0; index < resetEvents.Length; index++)
      {
        if (resetEvents[index].WaitOne(0))
        {
          MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Event {0} is available for work",resetEvents[index].SafeWaitHandle.DangerousGetHandle().ToString()));
          availableEvents.Add(resetEvents[index]);
        }
      }
      return availableEvents.ToArray();
    }
  }
}
