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

namespace MarketData.Helper
{
  public class PricingThreadHelper : ThreadHelper
  {
		private DateTime pricingDate=DateTime.Parse("12-31-9999");
		private DateTime? startDate;
		private TimeZoneHelper timeZoneInfo;

		public PricingThreadHelper(String symbol,ManualResetEvent resetEvent)
		{
			Symbol=symbol;
			ResetEvent=resetEvent;
		}
    public PricingThreadHelper(String symbol, DateTime pricingDate,ManualResetEvent resetEvent)
    {
      Symbol = symbol;
			this.pricingDate=pricingDate;
      ResetEvent = resetEvent;
			timeZoneInfo=new TimeZoneHelper(pricingDate);
    }
    public PricingThreadHelper(String symbol, ManualResetEvent resetEvent,DateTime? startDate=null)
    {
      Symbol = symbol;
			this.pricingDate=DateTime.Now;
			this.startDate=startDate;
      ResetEvent = resetEvent;
    }
		public TimeZoneHelper TimeZoneInfo
		{
			get{return timeZoneInfo;}
		}
		public DateTime PricingDate
		{
			get{return pricingDate;}
		}
		public DateTime? StartDate
		{
			get{return startDate;}
		}
  }
  public class PricingMarketDataHelper
  {
    private static int MaxThreads = (int)ThreadHelperEnum.MaxThreads;
    private static int WaitBetweenRequests=125;
    private List<String> symbols;
    private int currentIndex = 0;

    public PricingMarketDataHelper()
    {
    }
    public static Price RollPriceForward(String symbol)
    {
      try
      {
        DateGenerator dateGenerator=new DateGenerator();
        DateTime latestDate=PremarketDA.GetLatestMarketDate();
        if(Utility.IsEpoch(latestDate))return null;
        Price latestPrice=PricingDA.GetPrice(symbol);
        if(null==latestPrice)return null;
        DateTime latestPriceDateSymbol=latestPrice.Date;
        latestPrice.Date=latestDate;
        PricingDA.InsertPrice(latestPrice);
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("{0} price rolled forward from {1} to {2}",symbol,latestPriceDateSymbol.ToShortDateString(),latestDate.ToShortDateString()));
        return latestPrice;
      }
      catch(Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception rolling price forward for {0}.  Exception was {1}",symbol,exception.ToString()));
        return null;
      }
    }
		public bool UpdateLatestPriceAll()
		{
			Profiler profiler=new Profiler();
			try
			{
				symbols = PricingDA.GetSymbols();
				currentIndex=0;
				while (true)
				{
					List<String> queueSymbols = GetQueueSymbols();
					if (null == queueSymbols || 0 == queueSymbols.Count) break;
					ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count];
					for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++)
					{
						resetEvents[eventIndex] = new ManualResetEvent(false);
					}
					for (int index = 0; index < queueSymbols.Count; index++)
					{
						PricingThreadHelper pricingThreadHelper = new PricingThreadHelper(queueSymbols[index],resetEvents[index]);
						ThreadPool.QueueUserWorkItem(ThreadPoolCallbackUpdateLatestPriceAll, pricingThreadHelper);
            try{Thread.Sleep(WaitBetweenRequests);}catch(Exception){;}
					}
					MDTrace.WriteLine(LogLevel.DEBUG,"UpdateLatestPriceAll, waiting for queued items to complete.");
					WaitHandle.WaitAll(resetEvents);
				}
				return true;
			}
			finally
			{
				MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[UpdateLatestPriceAll]End, total took {0}(ms)",profiler.End()));
			}
		}
		public bool UpdatePricesBigCharts(DateTime? startDate=null)   // get prices from BigCharts
		{
			Profiler profiler=new Profiler();
			try
			{
				symbols = PricingDA.GetSymbols();
				currentIndex=0;
				if(null==startDate)startDate=DateTime.Now;
				TimeZoneHelper timeZoneHelper=new TimeZoneHelper(startDate.Value);
				while (true)
				{
					List<String> queueSymbols = GetQueueSymbols();
					if (null == queueSymbols || 0 == queueSymbols.Count) break;
					ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count];
					for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++)
					{
						resetEvents[eventIndex] = new ManualResetEvent(false);
					}
					for (int index = 0; index < queueSymbols.Count; index++)
					{
						PricingThreadHelper pricingThreadHelper = new PricingThreadHelper(queueSymbols[index],startDate.Value,resetEvents[index]);
						ThreadPool.QueueUserWorkItem(ThreadPoolCallbackUpdatePricesBigCharts, pricingThreadHelper);
            try{Thread.Sleep(WaitBetweenRequests);}catch(Exception){;}
					}
					MDTrace.WriteLine(LogLevel.DEBUG,"UpdatePricesBigCharts, waiting for queued items to complete.");
					WaitHandle.WaitAll(resetEvents);
				}
				return true;
			}
			finally
			{
				MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[UpdatePricesBigCharts]End, total took {0}(ms)",profiler.End()));
			}	
		}
    public bool UpdatePricesYahoo(DateTime? startDate=null)   // get prices from Yahoo
    {
      Profiler profiler=new Profiler();
      try
      {
        symbols=PricingDA.GetSymbols();
        currentIndex=0;
        if(null==startDate) startDate=DateTime.Now;
        TimeZoneHelper timeZoneHelper=new TimeZoneHelper(startDate.Value);
        while(true)
        {
          List<String> queueSymbols=GetQueueSymbols();
          if(null==queueSymbols||0==queueSymbols.Count) break;
          ManualResetEvent[] resetEvents=new ManualResetEvent[queueSymbols.Count];
          for(int eventIndex=0;eventIndex<resetEvents.Length;eventIndex++)
          {
            resetEvents[eventIndex]=new ManualResetEvent(false);
          }
          for(int index=0;index<queueSymbols.Count;index++)
          {
            PricingThreadHelper pricingThreadHelper=new PricingThreadHelper(queueSymbols[index],startDate.Value,resetEvents[index]);
            ThreadPool.QueueUserWorkItem(ThreadPoolCallbackUpdatePricesYahoo,pricingThreadHelper);
            try{Thread.Sleep(WaitBetweenRequests);}catch(Exception){;}
          }
          MDTrace.WriteLine(LogLevel.DEBUG,"UpdatePricesYahoo, waiting for queued items to complete.");
          WaitHandle.WaitAll(resetEvents);
        }
        return true;
      }
      finally
      {
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[UpdatePricesBigCharts]End, total took {0}(ms)",profiler.End()));
      }
    }
    public bool UpdatePricesYahooSweep(DateTime? startDate=null)   // get prices from Yahoo
    {
      Profiler profiler=new Profiler();
      try
      {
        symbols=PricingDA.GetSymbols();
        currentIndex=0;
        if(null==startDate) startDate=DateTime.Now;
        TimeZoneHelper timeZoneHelper=new TimeZoneHelper(startDate.Value);
        while(true)
        {
          List<String> queueSymbols=GetQueueSymbols();
          if(null==queueSymbols||0==queueSymbols.Count) break;
          ManualResetEvent[] resetEvents=new ManualResetEvent[queueSymbols.Count];
          for(int eventIndex=0;eventIndex<resetEvents.Length;eventIndex++)
          {
            resetEvents[eventIndex]=new ManualResetEvent(false);
          }
          for(int index=0;index<queueSymbols.Count;index++)
          {
            PricingThreadHelper pricingThreadHelper=new PricingThreadHelper(queueSymbols[index],startDate.Value,resetEvents[index]);
            ThreadPool.QueueUserWorkItem(ThreadPoolCallbackUpdatePricesYahooSweep,pricingThreadHelper);
            try{Thread.Sleep(WaitBetweenRequests);}catch(Exception){;}
          }
          MDTrace.WriteLine(LogLevel.DEBUG,"UpdatePricesYahooSweep, waiting for queued items to complete.");
          WaitHandle.WaitAll(resetEvents);
        }
        return true;
      }
      finally
      {
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[UpdatePricesBigCharts]End, total took {0}(ms)",profiler.End()));
      }
    }
		public bool UpdatePricesAsOfSymbol(String symbol,DateTime asOf)  // get prices from BigCharts
		{
			Profiler profiler=new Profiler();
			try
			{
				symbols=new List<String>();
				symbols.Add(symbol);
				currentIndex=0;
				while (true)
				{
					List<String> queueSymbols = GetQueueSymbols();
					if (null == queueSymbols || 0 == queueSymbols.Count) break;
					ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count];
					for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++)
					{
						resetEvents[eventIndex] = new ManualResetEvent(false);
					}
					for (int index = 0; index < queueSymbols.Count; index++)
					{
						PricingThreadHelper pricingThreadHelper = new PricingThreadHelper(queueSymbols[index], resetEvents[index],asOf);
						ThreadPool.QueueUserWorkItem(ThreadPoolCallbackUpdatePricesAsOf, pricingThreadHelper);
            try{Thread.Sleep(WaitBetweenRequests);}catch(Exception){;}
					}
					MDTrace.WriteLine(LogLevel.DEBUG,"UpdatePricesAsOfSymbol, waiting for queued items to complete.");
					WaitHandle.WaitAll(resetEvents);
				}
				return true;
			}
			finally
			{
				MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[UpdatePricesAsOfSymbol]End, total took {0}(ms)",profiler.End()));
			}	
		}
    public bool UpdatePriceAsOfSymbolYahoo(String symbol,DateTime asOf)  // get prices from Yahoo
    {
      Profiler profiler=new Profiler();
      try
      {
        symbols=new List<String>();
        symbols.Add(symbol);
        currentIndex=0;
        while(true)
        {
          List<String> queueSymbols=GetQueueSymbols();
          if(null==queueSymbols||0==queueSymbols.Count) break;
          ManualResetEvent[] resetEvents=new ManualResetEvent[queueSymbols.Count];
          for(int eventIndex=0;eventIndex<resetEvents.Length;eventIndex++)
          {
            resetEvents[eventIndex]=new ManualResetEvent(false);
          }
          for(int index=0;index<queueSymbols.Count;index++)
          {
            PricingThreadHelper pricingThreadHelper=new PricingThreadHelper(queueSymbols[index],asOf,resetEvents[index]);
            ThreadPool.QueueUserWorkItem(ThreadPoolCallbackUpdatePricesYahoo,pricingThreadHelper);
            try{Thread.Sleep(WaitBetweenRequests);}catch(Exception){;}
          }
          MDTrace.WriteLine(LogLevel.DEBUG,"UpdatePricesAsOfSymbol, waiting for queued items to complete.");
          WaitHandle.WaitAll(resetEvents);
        }
        return true;
      }
      finally
      {
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[UpdatePricesAsOfSymbol]End, total took {0}(ms)",profiler.End()));
      }
    }
		public bool UpdatePricesAsOf(DateTime asOf)
		{
			Profiler profiler=new Profiler();
			try
			{
				symbols=PricingDA.GetSymbols();
				currentIndex=0;
				while (true)
				{
					List<String> queueSymbols = GetQueueSymbols();
					if (null == queueSymbols || 0 == queueSymbols.Count) break;
					ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count];
					for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++)
					{
						resetEvents[eventIndex] = new ManualResetEvent(false);
					}
					for (int index = 0; index < queueSymbols.Count; index++)
					{
						PricingThreadHelper pricingThreadHelper = new PricingThreadHelper(queueSymbols[index], resetEvents[index],asOf);
						ThreadPool.QueueUserWorkItem(ThreadPoolCallbackUpdatePricesAsOf, pricingThreadHelper);
            try{Thread.Sleep(WaitBetweenRequests);}catch(Exception){;}
					}
					MDTrace.WriteLine(LogLevel.DEBUG,"UpdatePricesAsOf, waiting for queued items to complete.");
					WaitHandle.WaitAll(resetEvents);
				}
				return true;
			}
			finally
			{
				MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[UpdatePricesAsOf]End, total took {0}(ms)",profiler.End()));
			}
		}
		public bool GetMissingPricesSymbol(String symbol,DateTime? startDate=null)
		{
			Profiler profiler=new Profiler();
			try
			{
        List<String> symbols=new List<String>();
        symbols.Add(symbol);
				this.symbols=symbols;
				currentIndex = 0;
				while (true)
				{
					List<String> queueSymbols = GetQueueSymbols();
					if (null == queueSymbols || 0 == queueSymbols.Count) break;
					ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count];
					for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++)
					{
						resetEvents[eventIndex] = new ManualResetEvent(false);
					}
					for (int index = 0; index < queueSymbols.Count; index++)
					{
						PricingThreadHelper pricingThreadHelper = new PricingThreadHelper(queueSymbols[index], resetEvents[index],startDate);
						ThreadPool.QueueUserWorkItem(ThreadPoolCallbackGetMissingPrice, pricingThreadHelper);
            try{Thread.Sleep(WaitBetweenRequests);}catch(Exception){;}
					}
					MDTrace.WriteLine(LogLevel.DEBUG,"Get missing prices, waiting for queued items to complete.");
					WaitHandle.WaitAll(resetEvents);
				}
				return true;
			}
			finally
			{
				MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[GetMissingPrices]End, total took {0}(ms)",profiler.End()));
			}
		}
		public bool GetMissingPrices(DateTime? startDate=null)
		{
			Profiler profiler=new Profiler();
			try
			{
				this.symbols=PricingDA.GetSymbols();
				currentIndex = 0;
				while (true)
				{
					List<String> queueSymbols = GetQueueSymbols();
					if (null == queueSymbols || 0 == queueSymbols.Count) break;
					ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count];
					for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++)
					{
						resetEvents[eventIndex] = new ManualResetEvent(false);
					}
					for (int index = 0; index < queueSymbols.Count; index++)
					{
						PricingThreadHelper pricingThreadHelper = new PricingThreadHelper(queueSymbols[index], resetEvents[index],startDate);
						ThreadPool.QueueUserWorkItem(ThreadPoolCallbackGetMissingPrice, pricingThreadHelper);
            try{Thread.Sleep(WaitBetweenRequests);}catch(Exception){;}
					}
					MDTrace.WriteLine(LogLevel.DEBUG,"Get missing prices, waiting for queued items to complete.");
					WaitHandle.WaitAll(resetEvents);
				}
				return true;
			}
			finally
			{
				MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[GetMissingPrices]End, total took {0}(ms)",profiler.End()));
			}
		}
		public bool UpdateLatestPriceSymbol(String symbol)
		{
			List<String> symbols=new List<String>();
			symbols.Add(symbol);
			return UpdateLatestPrices(symbols);
		}
		public bool UpdateLatestPrices(List<String> symbols)
		{
			Profiler profiler=new Profiler();
			try
			{
				DateTime pricingDate=DateTime.Now;
				this.symbols = symbols;
				currentIndex = 0;
				while (true)
				{
					List<String> queueSymbols = GetQueueSymbols();
					if (null == queueSymbols || 0 == queueSymbols.Count) break;
					ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count];
					for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++)
					{
						resetEvents[eventIndex] = new ManualResetEvent(false);
					}
					for (int index = 0; index < queueSymbols.Count; index++)
					{
						PricingThreadHelper pricingThreadHelper = new PricingThreadHelper(queueSymbols[index], pricingDate,resetEvents[index]);
						ThreadPool.QueueUserWorkItem(ThreadPoolCallbackUpdateLatestPrice, pricingThreadHelper);
            try{Thread.Sleep(WaitBetweenRequests);}catch(Exception){;}
					}
					MDTrace.WriteLine(LogLevel.DEBUG,"Load prices, waiting for queued items to complete.");
					WaitHandle.WaitAll(resetEvents);
				}
				return true;
			}
			finally
			{
				MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[UpdateLatestPrices]End, total took {0}(ms)",profiler.End()));
			}
		}
    public bool LoadPrices(List<String> symbols)
    {
			Profiler profiler=new Profiler();
			try
			{
				DateTime pricingDate=DateTime.Now;
				this.symbols = symbols;
				currentIndex = 0;
				while (true)
				{
					List<String> queueSymbols = GetQueueSymbols();
					if (null == queueSymbols || 0 == queueSymbols.Count) break;
					ManualResetEvent[] resetEvents = new ManualResetEvent[queueSymbols.Count];
					for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++)
					{
						resetEvents[eventIndex] = new ManualResetEvent(false);
					}
					for (int index = 0; index < queueSymbols.Count; index++)
					{
						PricingThreadHelper pricingThreadHelper = new PricingThreadHelper(queueSymbols[index], pricingDate,resetEvents[index]);
						ThreadPool.QueueUserWorkItem(ThreadPoolCallbackLoadPrices, pricingThreadHelper);
            try{Thread.Sleep(WaitBetweenRequests);}catch(Exception){;}
					}
					MDTrace.WriteLine(LogLevel.DEBUG,"Load prices, waiting for queued items to complete.");
					WaitHandle.WaitAll(resetEvents);
				}
				return true;
			}
			finally
			{
				MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[LoadPrices]End, total took {0}(ms)",profiler.End()));
			}
    }
// ************************************************************************************************************************************
// *************************************************** T H R E A D P O O L   C A L L B A C K ******************************************
// ************************************************************************************************************************************
		public void ThreadPoolCallbackUpdateLatestPriceAll(Object pricingThreadHelperContext)
		{
      PricingThreadHelper pricingThreadHelper = (PricingThreadHelper)pricingThreadHelperContext;
			try
			{
				MDTrace.WriteLine(LogLevel.DEBUG,String.Format("UpdateLatestPriceAll, Thread {0} started for {1}...", Thread.CurrentThread.ManagedThreadId, pricingThreadHelper.Symbol));
				UpdateLatestPriceAllEx(pricingThreadHelper.Symbol);
				MDTrace.WriteLine(LogLevel.DEBUG,String.Format("UpdateLatestPriceAll, Thread {0} ended for {1}", Thread.CurrentThread.ManagedThreadId, pricingThreadHelper.Symbol));
			}
			finally
			{
			  pricingThreadHelper.ResetEvent.Set();
			}
		}
		public void ThreadPoolCallbackUpdatePricesBigCharts(Object pricingThreadHelperContext)
		{
      PricingThreadHelper pricingThreadHelper = (PricingThreadHelper)pricingThreadHelperContext;
			try
			{
				MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load price (BigCharts), Thread {0} started for {1}...", Thread.CurrentThread.ManagedThreadId, pricingThreadHelper.Symbol));
				UpdatePriceBigChartsEx(pricingThreadHelper.Symbol,pricingThreadHelper.TimeZoneInfo);
				MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load price (BigCharts), Thread {0} ended for {1}", Thread.CurrentThread.ManagedThreadId, pricingThreadHelper.Symbol));
			}
			finally
			{
			  pricingThreadHelper.ResetEvent.Set();
			}
		}
    public void ThreadPoolCallbackUpdatePricesYahoo(Object pricingThreadHelperContext)
    {
      PricingThreadHelper pricingThreadHelper=(PricingThreadHelper)pricingThreadHelperContext;
      try
      {
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load price (Yahoo), Thread {0} started for {1}...",Thread.CurrentThread.ManagedThreadId,pricingThreadHelper.Symbol));
        UpdatePriceYahoo(pricingThreadHelper.Symbol,pricingThreadHelper.TimeZoneInfo);
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load price (Yahoo), Thread {0} ended for {1}",Thread.CurrentThread.ManagedThreadId,pricingThreadHelper.Symbol));
      }
      finally
      {
        pricingThreadHelper.ResetEvent.Set();
      }
    }
    public void ThreadPoolCallbackUpdatePricesYahooSweep(Object pricingThreadHelperContext)
    {
      PricingThreadHelper pricingThreadHelper=(PricingThreadHelper)pricingThreadHelperContext;
      try
      {
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load price (Yahoo), Thread {0} started for {1}...",Thread.CurrentThread.ManagedThreadId,pricingThreadHelper.Symbol));
        UpdatePriceYahooSweep(pricingThreadHelper.Symbol,pricingThreadHelper.TimeZoneInfo);
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load price (Yahoo), Thread {0} ended for {1}",Thread.CurrentThread.ManagedThreadId,pricingThreadHelper.Symbol));
      }
      finally
      {
        pricingThreadHelper.ResetEvent.Set();
      }
    }
		public void ThreadPoolCallbackUpdatePricesAsOf(Object pricingThreadHelperContext)
		{
      PricingThreadHelper pricingThreadHelper = (PricingThreadHelper)pricingThreadHelperContext;
			try
			{
				MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load price, Thread {0} started for {1}...", Thread.CurrentThread.ManagedThreadId, pricingThreadHelper.Symbol));
				UpdatePriceAsOfEx(pricingThreadHelper.Symbol,pricingThreadHelper.StartDate.Value);
				MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load price, Thread {0} ended for {1}", Thread.CurrentThread.ManagedThreadId, pricingThreadHelper.Symbol));
			}
			finally
			{
			  pricingThreadHelper.ResetEvent.Set();
			}
		}
		public void ThreadPoolCallbackGetMissingPrice(Object pricingThreadHelperContext)
		{
      PricingThreadHelper pricingThreadHelper = (PricingThreadHelper)pricingThreadHelperContext;
			try
			{
        GetMissingPricesEx(pricingThreadHelper.Symbol,pricingThreadHelper.StartDate==null?new DateTime():pricingThreadHelper.StartDate.Value);
			}
			finally
			{
        pricingThreadHelper.ResetEvent.Set();
			}		
		}
    public void ThreadPoolCallbackUpdateLatestPrice(Object pricingThreadHelperContext)
    {
      PricingThreadHelper pricingThreadHelper = (PricingThreadHelper)pricingThreadHelperContext;
			try
			{
				Price latestPrice = MarketDataHelper.GetLatestPrice(pricingThreadHelper.Symbol);
				if (null == latestPrice)
				{
					MDTrace.WriteLine(LogLevel.DEBUG,String.Format("***** Error retrieving latest price for {0} *****",pricingThreadHelper.Symbol));
					return;
				}

				MDTrace.WriteLine(LogLevel.DEBUG,Price.Header);
				MDTrace.WriteLine(LogLevel.DEBUG,latestPrice.ToString());
				MDTrace.WriteLine(LogLevel.DEBUG,"Removing price for '"+pricingThreadHelper.Symbol+"' on "+Utility.DateTimeToStringMMSDDSYYYY(latestPrice.Date));
				PricingDA.DeletePrice(pricingThreadHelper.Symbol,latestPrice.Date);
				MDTrace.WriteLine(LogLevel.DEBUG,"Adding price for '" + pricingThreadHelper.Symbol + "' on " + Utility.DateTimeToStringMMSDDSYYYY(latestPrice.Date));
				PricingDA.InsertPrice(latestPrice);
			}
			finally
			{
        pricingThreadHelper.ResetEvent.Set();
			}
    }
    public void ThreadPoolCallbackLoadPrices(Object pricingThreadHelperContext)
    {
      PricingThreadHelper pricingThreadHelper = (PricingThreadHelper)pricingThreadHelperContext;
			try
			{
				MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load price, Thread {0} started for {1}...", Thread.CurrentThread.ManagedThreadId, pricingThreadHelper.Symbol));
				LoadPricesSymbolEx(pricingThreadHelper.Symbol,pricingThreadHelper.PricingDate);
				MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load price, Thread {0} ended for {1}", Thread.CurrentThread.ManagedThreadId, pricingThreadHelper.Symbol));
			}
			finally
			{
			  pricingThreadHelper.ResetEvent.Set();
			}
    }
// ****************************************************************************************************************************************
// ****************************************************************************************************************************************
// ****************************************************************************************************************************************
    private List<String> GetQueueSymbols()
    {
      List<String> queueSymbols = new List<String>();
      int index = currentIndex;
      for (; index < currentIndex + MaxThreads && index < symbols.Count; index++)
      {
        queueSymbols.Add(symbols[index]);
      }
      currentIndex = index;
      return queueSymbols;
    }
// ********************************************************************************************************************************************
// ************************************************************ W O R K E R S *****************************************************************
// ********************************************************************************************************************************************
    public static void GetMissingPricesEx(String symbol,DateTime startDate)
    {
      try
      {
        DateGenerator dateGenerator=new DateGenerator();
        TimeSpan oneDay=new TimeSpan(1,0,0,0);
        DateTime? historicalDate = null;
        DateTime minDate=Constants.MIN_PRICING_DATE;

        List<DateTime> pricingDatesList = PricingDA.GetPricingDatesForSymbol(symbol);
        if (null == pricingDatesList || 0 == pricingDatesList.Count) return;
        pricingDatesList=pricingDatesList.Where(x => x.Date>=minDate.Date).ToList();
        if(null==pricingDatesList||0==pricingDatesList.Count) return;
        DateTime beginDate = pricingDatesList[0];
        DateTime endDate = pricingDatesList[pricingDatesList.Count - 1];
        Dictionary<DateTime, DateTime> pricingDates = new Dictionary<DateTime, DateTime>();
        for (int listIndex = 0; listIndex < pricingDatesList.Count; listIndex++)
        {
          DateTime pricingDate=pricingDatesList[listIndex];
          pricingDates.Add(pricingDate.Date, pricingDate.Date);
        }
        Dictionary<DateTime, Price> marketPrices = new Dictionary<DateTime, Price>();
        if (Utility.IsEpoch(startDate)) historicalDate = beginDate;
        else historicalDate = startDate;
        MDTrace.WriteLine(LogLevel.DEBUG,"Working on '" + symbol + "' from "+Utility.DateTimeToStringMMHDDHYYYY(historicalDate.Value)+" to "+Utility.DateTimeToStringMMHDDHYYYY(endDate));
        Prices prices = MarketDataHelper.GetDailyPrices(symbol, historicalDate.Value, endDate);                        // yahoo finance
        if(null==prices||0==prices.Count)prices=MarketDataHelper.GetPricesAsOf(symbol,historicalDate.Value,endDate);   // try big charts
        if (null == prices||0==prices.Count)return;
        for (int listIndex = 0; listIndex < prices.Count; listIndex++)
        {
          Price price = prices[listIndex];
          if(!marketPrices.ContainsKey(price.Date.Date))marketPrices.Add(price.Date,price);
        }
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Retrieved {0} prices from feed for {1}",prices.Count,symbol));
        bool added=false;
        for (DateTime date = historicalDate.Value.Date; date < endDate.Date; date += oneDay)
        {
          if (pricingDates.ContainsKey(date.Date)) continue;
          if (dateGenerator.IsWeekend(date)) continue;
          Price price = null;
          if (!marketPrices.ContainsKey(date.Date))continue;
          MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Inserting price {0}...",price.ToString()));
          price = marketPrices[date.Date];
          MDTrace.WriteLine(LogLevel.DEBUG,price.ToString());
          PricingDA.InsertPrice(price);
          added=true;
        }
        if(!added)
        {
          MDTrace.WriteLine(LogLevel.DEBUG,"There were no new prices to add for '" + symbol);
        }
      }
      catch(Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception {0}",exception.ToString()));
      }
    }
    public static void UpdateLatestPriceAllEx(String symbol)
    {
      try
      {
        symbol = symbol.ToUpper();
        Price latestPrice = MarketDataHelper.GetLatestPrice(symbol);
        if (null == latestPrice)
        {
          MDTrace.WriteLine(LogLevel.DEBUG,"Error retrieving latest price.");
          return;
        }
        MDTrace.WriteLine(LogLevel.DEBUG,Price.Header);
        MDTrace.WriteLine(LogLevel.DEBUG,latestPrice.ToString());
        MDTrace.WriteLine(LogLevel.DEBUG,"Removing price for '" + symbol + "' on " + Utility.DateTimeToStringMMSDDSYYYY(latestPrice.Date));
        PricingDA.DeletePrice(symbol, latestPrice.Date);
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Inserting price {0}...",latestPrice.ToString()));
        PricingDA.InsertPrice(latestPrice);
      }
      catch(Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
      }
    }
		public static void UpdatePriceBigChartsEx(String symbol,TimeZoneHelper timeZoneInfo)
		{
			try
			{
        Price price=PricingDA.GetPrice(symbol,timeZoneInfo.StartDate);
        if(null!=price)
				{
					MDTrace.WriteLine(LogLevel.DEBUG,"Already have latest price for '" + symbol + "'");
					return;
				}
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Requesting price for {0} for start date:{1} end date:{2}",symbol,timeZoneInfo.StartDate,timeZoneInfo.StartDate));
				Prices prices = MarketDataHelper.GetPricesAsOf(symbol, timeZoneInfo.StartDate,timeZoneInfo.StartDate);
				if (null == prices||0==prices.Count)
				{
					MDTrace.WriteLine(LogLevel.DEBUG,"No prices (GetPricesAsOf) for '" + symbol+ "'");
					return;
				}
				else
				{
					for (int secIndex = 0; secIndex < prices.Count; secIndex++)
					{
						MDTrace.WriteLine(LogLevel.DEBUG,prices[secIndex].ToString());
					}
					MDTrace.WriteLine(LogLevel.DEBUG,"Inserting....");
					PricingDA.InsertPrices(prices);
					MDTrace.WriteLine(LogLevel.DEBUG,"Done.");
				}
			}
			catch(Exception exception)
			{
				MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception {0}",exception.ToString()));
			}
		}
    public static void UpdatePriceYahoo(String symbol,TimeZoneHelper timeZoneInfo)
    {
      try
      {
        Price price=PricingDA.GetPrice(symbol,timeZoneInfo.StartDate);
        if(null!=price)
        {
          MDTrace.WriteLine(LogLevel.DEBUG,"Already have latest price for '"+symbol+"'");
          return;
        }
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Requesting price for {0} for start date:{1} end date:{2}",symbol,timeZoneInfo.StartDate,timeZoneInfo.StartDate));
        price=MarketDataHelper.GetDailyPrice(symbol,timeZoneInfo.StartDate);
        if(null==price)
        {
          MDTrace.WriteLine(LogLevel.DEBUG,"No price (UpdatePriceYahoo) for '"+symbol+"'");
          return;
        }
        else
        {
          MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Inserting price {0}...",price.ToString()));
          PricingDA.InsertPrice(price);
        }
      }
      catch(Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception {0}",exception.ToString()));
      }
    }
    public static void UpdatePriceYahooSweep(String symbol,TimeZoneHelper timeZoneInfo)
    {
      try
      {
        CompanyProfile companyProfile=CompanyProfileDA.GetCompanyProfile(symbol);
        Price price=PricingDA.GetPrice(symbol,timeZoneInfo.StartDate);
        if(null!=price)
        {
          if(companyProfile==null || !companyProfile.PricingSourceEnum.Equals(CompanyProfile.EnumPricingSource.YAHOO))
          {
            MDTrace.WriteLine(LogLevel.DEBUG,"Already have latest price for '"+symbol+"'");
            return;
          }
        }
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("UpdatePriceYahooSweep: Requesting price for {0} for start date:{1} end date:{2}",symbol,timeZoneInfo.StartDate,timeZoneInfo.StartDate));
        price=MarketDataHelper.GetDailyPrice(symbol,timeZoneInfo.StartDate);
        if(null==price)
        {
          MDTrace.WriteLine(LogLevel.DEBUG,"No price (UpdatePriceYahoo) for '"+symbol+"'");
          return;
        }
        else if(!price.IsValid)
        {
          MDTrace.WriteLine(LogLevel.DEBUG,"Invalid price (UpdatePriceYahooSweep) for '"+symbol+"'");
          return;
        }
        else
        {
          MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Inserting price {0}...",price.ToString()));
          PricingDA.InsertPrice(price);
        }
      }
      catch(Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception {0}",exception.ToString()));
      }
    }
		public static void UpdatePriceAsOfEx(String symbol,DateTime asOf)
		{
			try
			{
				DateTime latestDate = PricingDA.GetLatestDate(symbol);
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Latest pricing date for {0} is {1}",symbol,latestDate.ToShortDateString()));
				if (latestDate.Equals(asOf))
				{
					MDTrace.WriteLine(LogLevel.DEBUG,"Already have price for '" + symbol + "' on "+Utility.DateTimeToStringMMHDDHYYYY(asOf));
					return;
				}
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Retrieving price for {0} on {1} from BigCharts",symbol,asOf.ToShortDateString()));
				Price price = MarketDataHelper.GetPriceAsOf(symbol,asOf);
				if (null == price)
				{
					MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Error retrieving price for {0} on {1}",symbol,asOf.ToShortDateString()));
					return;
				}
				MDTrace.WriteLine(LogLevel.DEBUG,Price.Header);
				MDTrace.WriteLine(LogLevel.DEBUG,price.ToString());
				MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Inserting price {0}...",price.ToString()));
				PricingDA.InsertPrice(price);
				MDTrace.WriteLine(LogLevel.DEBUG,"");
			}
			catch (Exception exception)
			{
				MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
			}
	  } 

    public static void LoadPricesSymbolEx(String symbol,DateTime pricingDate)
    {
      DateGenerator dateGenerator = new DateGenerator();
      DateTime startDate = pricingDate;    // the least recent date
      DateTime endDate = pricingDate;      // the most recent date
      endDate = dateGenerator.GetPrevBusinessDay(endDate);
      startDate = PricingDA.GetLatestDate(symbol);
      startDate = dateGenerator.FindNextBusinessDay(startDate);
      if (startDate.Date > endDate.Date)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,"Already have latest price for '" + symbol + "'");
        return;
      }
      Prices prices=MarketDataHelper.GetPricesAsOf(symbol,startDate,endDate);
      if (null == prices||0==prices.Count)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,"No prices (GetDailyPrices) for '" + symbol + "'");
        return;
      }
      else
      {
        for (int secIndex = 0; secIndex < prices.Count; secIndex++)
        {
          MDTrace.WriteLine(LogLevel.DEBUG,prices[secIndex].ToString());
        }
        PricingDA.InsertPrices(prices);
        MDTrace.WriteLine(LogLevel.DEBUG,"Done.");
      }
    }
  }
}

