using System;
using System.Threading;
using MarketData.MarketDataModel;
using MarketData.DataAccess;
using MarketData.Utils;

namespace MarketData.Helper
{
  public class CompanyProfileThreadHelper : ThreadHelper
  {
    public CompanyProfile CompanyProfile{get;set;}

		public CompanyProfileThreadHelper()
		{
		}
    public CompanyProfileThreadHelper(CompanyProfile companyProfile, ManualResetEvent resetEvent)
    {
      CompanyProfile=companyProfile;
      ResetEvent=resetEvent;
    }
  }
  public class CompanyProfileMarketDataHelper
  {
    private static int MaxThreads = (int)ThreadHelperEnum.MaxThreads;
    private CompanyProfiles companyProfiles;
    private int currentIndex = 0;

    public CompanyProfileMarketDataHelper()
    {
    }
    public bool UpdateCompanyProfile(String symbol)
    {
			Profiler profiler=new Profiler();
			try
			{
				companyProfiles=new CompanyProfiles();
        CompanyProfile companyProfile=CompanyProfileDA.GetCompanyProfile(symbol);
        if(null==companyProfile)return false;
        companyProfiles.Add(companyProfile);
				currentIndex = 0;
				while (true)
				{
					CompanyProfiles queueProfiles = GetQueueProfiles();
					if (null == queueProfiles || 0 == queueProfiles.Count) break;
					ManualResetEvent[] resetEvents = new ManualResetEvent[queueProfiles.Count];
					for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++)
					{
						resetEvents[eventIndex] = new ManualResetEvent(false);
					}
					for (int index = 0; index < queueProfiles.Count; index++)
					{
						CompanyProfileThreadHelper companyProfileThreadHelper = new CompanyProfileThreadHelper(queueProfiles[index],resetEvents[index]);
						ThreadPool.QueueUserWorkItem(ThreadPoolCallback, companyProfileThreadHelper);
					}
					MDTrace.WriteLine(LogLevel.DEBUG,"Load company profile, waiting for queued items to complete.");
					WaitHandle.WaitAll(resetEvents);
				}
				return true;
			}
			finally
			{
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[UpdateCompanyProfiles]End, total took {0}(ms)",profiler.End()));
			}
    }
    public bool UpdateCompanyProfiles()
    {
			Profiler profiler=new Profiler();
			try
			{
				companyProfiles=CompanyProfileDA.GetCompanyProfiles();
				currentIndex = 0;
				while (true)
				{
					CompanyProfiles queueProfiles = GetQueueProfiles();
					if (null == queueProfiles || 0 == queueProfiles.Count) break;
					ManualResetEvent[] resetEvents = new ManualResetEvent[queueProfiles.Count];
					for (int eventIndex = 0; eventIndex < resetEvents.Length; eventIndex++)
					{
						resetEvents[eventIndex] = new ManualResetEvent(false);
					}
					for (int index = 0; index < queueProfiles.Count; index++)
					{
						CompanyProfileThreadHelper companyProfileThreadHelper = new CompanyProfileThreadHelper(queueProfiles[index],resetEvents[index]);
						ThreadPool.QueueUserWorkItem(ThreadPoolCallback, companyProfileThreadHelper);
					}
					MDTrace.WriteLine(LogLevel.DEBUG,"Load company profile, waiting for queued items to complete.");
					WaitHandle.WaitAll(resetEvents);
				}
				return true;
			}
			finally
			{
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("[UpdateCompanyProfiles]End, total took {0}(ms)",profiler.End()));
			}
    }
    private CompanyProfiles GetQueueProfiles()
    {
      CompanyProfiles queueProfiles = new CompanyProfiles();
      int index = currentIndex;
      for (; index < currentIndex + MaxThreads && index < companyProfiles.Count; index++)
      {
        queueProfiles.Add(companyProfiles[index]);
      }
      currentIndex = index;
      return queueProfiles;
    }
    public void ThreadPoolCallback(Object companyProfileThreadHelperContext)
    {
      CompanyProfileThreadHelper companyProfileThreadHelper = (CompanyProfileThreadHelper)companyProfileThreadHelperContext;
      MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load profile, Thread {0} started for {1}...", Thread.CurrentThread.ManagedThreadId, companyProfileThreadHelper.CompanyProfile.Symbol));
      LoadCompanyProfileEx(companyProfileThreadHelper.CompanyProfile);
      MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Load profile, Thread {0} ended for {1}", Thread.CurrentThread.ManagedThreadId,  companyProfileThreadHelper.CompanyProfile.Symbol));
      companyProfileThreadHelper.ResetEvent.Set();
    }
    private static void LoadCompanyProfileEx(CompanyProfile companyProfile)
    {
      CompanyProfile marketCompanyProfile = MarketDataHelper.GetCompanyProfile(companyProfile.Symbol);
      if (null == marketCompanyProfile)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,"No company profile for symbol '" + companyProfile.Symbol + "'");
        return;
      }
			if(!String.IsNullOrEmpty(marketCompanyProfile.Sector) && !marketCompanyProfile.Sector.Equals("N/A"))companyProfile.Sector=marketCompanyProfile.Sector;
			if(!String.IsNullOrEmpty(marketCompanyProfile.Industry) && !marketCompanyProfile.Industry.Equals("N/A"))companyProfile.Industry=marketCompanyProfile.Industry;
      if(!String.IsNullOrEmpty(marketCompanyProfile.Description) && !marketCompanyProfile.Description.Equals("N/A"))companyProfile.Description=marketCompanyProfile.Description;
      MDTrace.WriteLine(LogLevel.DEBUG,String.Format("LoadCompanyProfileEx: Updating company profile.....Symbol:{0} Sector:{1} Industry:{2}",companyProfile.Symbol,companyProfile.Sector, companyProfile.Industry));
      CompanyProfileDA.UpdateCompanyProfile(companyProfile);
		}
  }
}

