using MarketData.DataAccess;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MarketData.MarketDataModel
{
// ********************************************************************************************************************************************************
// ******************************************** U N I T   T E S T  F O R  J O E L   G R E E N B L A T T   M E T H O D O L O G Y ***************************
// ********************************************************************************************************************************************************
    public class TLBItemList : List<TLBItem>
    {
      public TLBItemList()
      {
      }
      public TLBItemList(TLBItemList itemList)
      {
        foreach(TLBItem item in itemList)Add(item);
      }
      public static void ApplyTLBRanks(TLBItemList items)
      {
        Dictionary<String,TLBItem> itemsBySymbol=new Dictionary<String,TLBItem>();
        Dictionary<String,int> itemsRankedByROC=new Dictionary<String,int>();
        Dictionary<String,int> itemsRankedByROIC=new Dictionary<String,int>();
        Dictionary<String,int> itemsRankedByEarningsYield=new Dictionary<String,int>();

        foreach(TLBItem item in items)
        {
          if(!itemsBySymbol.ContainsKey(item.Symbol))
          {
            itemsBySymbol.Add(item.Symbol,item);
          }
        }

        TLBItemList itemsCopyByROC=new TLBItemList(items);
        TLBItemList itemsCopyByROIC=new TLBItemList(items);
        TLBItemList itemsCopyByEarningsYield=new TLBItemList(items);            
        itemsCopyByROC.Sort(new TLBListByROC());
        itemsCopyByROIC.Sort(new TLBListByROIC());
        itemsCopyByEarningsYield.Sort(new TLBListByEarningsYield());

        for(int index=0;index<itemsCopyByROC.Count;index++)
        {
          String symbol=itemsCopyByROC[index].Symbol;
          if(!itemsRankedByROC.ContainsKey(symbol))itemsRankedByROC.Add(symbol,index);
        }
        for(int index=0;index<itemsCopyByROIC.Count;index++)
        {
          String symbol=itemsCopyByROIC[index].Symbol;
          if(!itemsRankedByROIC.ContainsKey(symbol))itemsRankedByROIC.Add(symbol,index);
        }
        for(int index=0;index<itemsCopyByEarningsYield.Count;index++)
        {
          String symbol=itemsCopyByEarningsYield[index].Symbol;
          if(!itemsRankedByEarningsYield.ContainsKey(symbol))itemsRankedByEarningsYield.Add(symbol,index);
        }

        for(int index=0;index<items.Count;index++)
        {
          TLBItem tlbItem=items[index];
          tlbItem.TLBRankROC=itemsRankedByROC[tlbItem.Symbol]+itemsRankedByEarningsYield[tlbItem.Symbol];
          tlbItem.TLBRankROIC=itemsRankedByROIC[tlbItem.Symbol]+itemsRankedByEarningsYield[tlbItem.Symbol];
        }
      }
    }
    public class TLBListByROC : IComparer<TLBItem>
    {
      public int Compare(TLBItem v1,TLBItem v2)
      {
        if(double.IsNaN(v1.ROC)&&double.IsNaN(v2.ROC))return 0;
        else if(double.IsNaN(v1.ROC))return -1;
        else if(double.IsNaN(v2.ROC))return 1;
        return v1.ROC.CompareTo(v2.ROC);
      }
    }
    public class TLBListByROIC : IComparer<TLBItem>
    {
      public int Compare(TLBItem v1,TLBItem v2)
      {
        if(double.IsNaN(v1.ROIC)&&double.IsNaN(v2.ROIC))return 0;
        else if(double.IsNaN(v1.ROIC))return -1;
        else if(double.IsNaN(v2.ROIC))return 1;
        return v1.ROIC.CompareTo(v2.ROIC);
      }
    }
    public class TLBListByEarningsYield : IComparer<TLBItem>
    {
      public int Compare(TLBItem v1,TLBItem v2)
      {
        if(double.IsNaN(v1.EarningsYield)&&double.IsNaN(v2.EarningsYield))return 0;
        else if(double.IsNaN(v1.EarningsYield))return -1;
        else if(double.IsNaN(v2.EarningsYield))return 1;
        return v1.EarningsYield.CompareTo(v2.EarningsYield);
      }
    }
    public class TLBItem
    {
      public String Symbol{get;set;}
      public double EBIT{get;set;}
      public double EarningsYield{get;set;}
      public double EnterpriseValue{get;set;}
      public double WorkingCapital{get;set;}
      public double PPE{get;set;}
      public double ROIC{get;set;}
      public double ROC{get;set;}
      public double TLBRankROIC{get;set;}
      public double TLBRankROC{get;set;}
    }
// The sorting of the ranks will be from lowest to highest.  The largest ROICS will have the largest ranks and the largest EarningsYields will have the largest ranks.
// This sorting is opposite to how Joel sorted his lists.  Joel's lists wind up with the best candidates having the lowest ranks while this one winds up with the 
// best candidates having the highest ranks.  This can be seen when visiting the Valuations view and changing the sort to TLBRankROIC with the highest valued ranks 
// on top.  These will be the top candidates.
  public class TLBRankGenerator
  {
    private TLBRankGenerator()
    {
    }
// *******************************************************************************************************************************************************************
// ********************************************** T H E  L I T T L E  B O O K  R A N K   G E N E R A T O R  U N I T  T E S T  ****  **********************************
// *******************************************************************************************************************************************************************
    public static TLBItemList ApplyTLBRanks()
    {
      List<String> symbols=PricingDA.GetSymbols();
      TLBItemList tlbList=new TLBItemList();
 
      foreach(String symbol in symbols)
      {
        double earningsYield=double.NaN;
        double roc=double.NaN;
        double roic=double.NaN;
        Console.WriteLine("Working on "+symbol);
 
        BalanceSheet balanceSheet = BalanceSheetDA.GetBalanceSheet(symbol,BalanceSheet.PeriodType.Annual);
        TimeSeriesCollection workingCapitalCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.WorkingCapital);
        TimeSeriesCollection roicCollection = HistoricalDA.GetTimeSeries(symbol, TimeSeriesElement.ElementType.ROIC);
        Fundamental fundamental=FundamentalDA.GetFundamental(symbol);
        if(null==fundamental)continue;
        TLBItem tlbItem=new TLBItem();
        if(!double.IsNaN(fundamental.EBIT)&&!double.IsNaN(fundamental.EnterpriseValue)&&fundamental.EnterpriseValue>0.00&&fundamental.EBIT>0.00)
        {
          earningsYield=fundamental.EBIT/fundamental.EnterpriseValue;
        }
        if(!double.IsNaN(fundamental.EBIT)&&null!=balanceSheet&&!double.IsNaN(balanceSheet.NetFixedAssets))
        {
          roc=fundamental.EBIT/balanceSheet.NetFixedAssets;
        }
        if(null!=roicCollection && roicCollection.Count>0)roic=roicCollection[0].Value;
        tlbItem.Symbol=symbol;
        tlbItem.EBIT=fundamental.EBIT;
        tlbItem.EarningsYield=earningsYield;
        tlbItem.EnterpriseValue=fundamental.EnterpriseValue;
        tlbItem.ROC=roc*100.00;
        tlbItem.ROIC=roic;
        tlbList.Add(tlbItem);
      }
      TLBItemList.ApplyTLBRanks(tlbList);
      return tlbList;
    }
// *******************************************************************************************************************************************************************
// ********************************************** T H E  L I T T L E  B O O K  R A N K   G E N E R A T O R  F O R  V A L U A T I O N   **********************************
// *******************************************************************************************************************************************************************
    public static void ApplyTLBRanks(Valuations valuations)
    {
      Dictionary<String,Valuation> valuationsBySymbol=new Dictionary<String,Valuation>();
      Dictionary<String,int> valuationsRankedByROIC=new Dictionary<String,int>();
      Dictionary<String,int> valuationsRankedByROC=new Dictionary<String,int>();
      Dictionary<String,int> valuationsRankedByEarningsYield=new Dictionary<String,int>();

      foreach(Valuation valuation in valuations)
      {
        if(!valuationsBySymbol.ContainsKey(valuation.Symbol))valuationsBySymbol.Add(valuation.Symbol,valuation);
      }
      Valuations valuationsCopyByROIC=new Valuations(valuations);
      valuationsCopyByROIC.Sort(new ValuationsByROIC());
      Valuations valuationsCopyByROC=new Valuations(valuations);
      valuationsCopyByROC.Sort(new ValuationsByROC());
      Valuations valuationsCopyByEarningsYield=new Valuations(valuations);            
      valuationsCopyByEarningsYield.Sort(new ValuationsByEarningsYield());
      for(int index=0;index<valuationsCopyByROIC.Count;index++)
      {
        String symbol=valuationsCopyByROIC[index].Symbol;
        if(!valuationsRankedByROIC.ContainsKey(symbol))valuationsRankedByROIC.Add(symbol,index);
      }
      for(int index=0;index<valuationsCopyByROC.Count;index++)
      {
        String symbol=valuationsCopyByROC[index].Symbol;
        if(!valuationsRankedByROC.ContainsKey(symbol))valuationsRankedByROC.Add(symbol,index);
      }
      for(int index=0;index<valuationsCopyByEarningsYield.Count;index++)
      {
        String symbol=valuationsCopyByEarningsYield[index].Symbol;
        if(!valuationsRankedByEarningsYield.ContainsKey(symbol))valuationsRankedByEarningsYield.Add(symbol,index);
      }
      for(int index=0;index<valuations.Count;index++)
      {
        Valuation valuation=valuations[index];
        valuation.TLBRankROIC=valuationsRankedByROIC[valuation.Symbol]+valuationsRankedByEarningsYield[valuation.Symbol];
        valuation.TLBRankROC=valuationsRankedByROC[valuation.Symbol]+valuationsRankedByEarningsYield[valuation.Symbol];
      }
    }
  }
}
