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

namespace TradeBlotter.Cache
{
  public class PriceCache : IDisposable
  {
    private Dictionary<String,Price> priceCache=new Dictionary<String,Price>();
    private Object thisLock=new Object();
    private Thread cacheMonitorThread=null;
    private volatile bool threadRun=true;
    private int cacheRefreshAfter=60000;
    private static PriceCache priceCacheInstance=null;

    private PriceCache()
    {
      cacheMonitorThread=new Thread(new ThreadStart(ThreadProc));
      cacheMonitorThread.Start();
    }
    public static PriceCache GetInstance()
    {
      lock(typeof(PriceCache))
      {
        if(null==priceCacheInstance) priceCacheInstance=new PriceCache();
        return priceCacheInstance;
      }
    }
    public void Clear()
    {
      lock(thisLock)
      {
        priceCache=new Dictionary<String,Price>();
      }
    }
    public void Dispose()
    {
      lock(thisLock)
      {
			  if(null==priceCacheInstance || false==threadRun)return;
        threadRun=false;
        if(null!=cacheMonitorThread)
        {
          MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[PriceCache:Dispose]Thread state is {0}.  Joining main thread...",Utility.ThreadStateToString(cacheMonitorThread)));
          cacheMonitorThread.Join(5000);
          cacheMonitorThread=null;
          MDTrace.WriteLine(LogLevel.DEBUG,"[PriceCache:Dispose] End.");
        }
        priceCacheInstance=null;
      }
    }
    public Price GetLatestPrice(String symbol)
    {
      lock(thisLock)
      {
        if(priceCache.ContainsKey(symbol))
        {
          return priceCache[symbol];
        }
        Price price=MarketDataHelper.GetLatestPrice(symbol);
        if(null!=price) Add(price);
        return price;
      }
    }
    public bool Contains(String symbol)
    {
      lock(thisLock)
      {
        return priceCache.ContainsKey(symbol);
      }
    }
    private void Add(Price price)
    {
      lock(thisLock)
      {
        if(priceCache.ContainsKey(price.Symbol)) return;
        priceCache.Add(price.Symbol,price);
      }
    }
    private void ThreadProc()
    {
      int quantums=0;
      int quantumInterval=1000;
      while(threadRun)
      {
        Thread.Sleep(quantumInterval);
        quantums+=quantumInterval;
        if(quantums>cacheRefreshAfter)
        {
          quantums=0;
          lock(thisLock)
          {
            priceCache.Clear();
          }
        }
      }
    }
  }
}
