using System;
using System.Windows.Input;
using System.ComponentModel;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Threading.Tasks;
using System.Windows;
using System.Linq;
using System.Text;
using MarketData;
using MarketData.Utils;
using MarketData.MarketDataModel;
using MarketData.DataAccess;
using TradeBlotter.DataAccess;
using TradeBlotter.Command;
using TradeBlotter.Helper;
using TradeBlotter.UIUtils;
using TradeBlotter.Model;

namespace TradeBlotter.ViewModels
{
    public class ValuationsViewModel : WorkspaceViewModel
    {
      private String selectedValuationDate;
      private String saveDocument=null;
      private RelayCommand displaySECFilingsCommand = null;
      private RelayCommand saveCommand = null;
      private RelayCommand stochasticsCommand = null;
      private RelayCommand relativeStrengthCommand = null;
      private RelayCommand macdCommand = null;
      private RelayCommand bollingerBandCommand = null;
      private RelayCommand priceHistoryCommand = null;
      private RelayCommand addToWatchListCommand = null;
      private RelayCommand removeFromWatchListCommand = null;
      private RelayCommand stickerValuationCommand = null;
      private RelayCommand dcfValuationCommand = null;
      private RelayCommand displayAnalystRatingsCommand = null;
      private RelayCommand displayHeadlinesCommand = null;
      private RelayCommand removeValuationCommand = null;
      private RelayCommand dividendHistoryCommand = null;
      private RelayCommand displayHistoricalCommand = null;
      private RelayCommand movingAverageCommand = null;
      private RelayCommand proformaDividendRiskCommand = null;
      private List<String> sortFilters;
      private String selectedSortFilter;
      private int saveCount = 0;
      private bool busyIndicator=false;
      private ValuationModel selectedItem = null;

      public ValuationsViewModel()
      {
        base.DisplayName = "Valuations";
        CreateSortFilters();
        SelectedSortFilter=sortFilters[0];
        PropertyChanged += OnValuationsViewModelPropertyChanged;
      }

      private void OnValuationsViewModelPropertyChanged(object sender, PropertyChangedEventArgs eventArgs)
      {
        if (eventArgs.PropertyName.Equals("SelectedValuationDate"))
        {
          CreateAllValuations();
        }
        if(eventArgs.PropertyName.Equals("SelectedSortFilter"))
        {
          CreateAllValuations();
        }
      }

      private void CreateSortFilters()
      {
        sortFilters=new List<String>();
        sortFilters.Add("Acquirers Multiple");
        sortFilters.Add("Joel Greenblatt (ROIC)");
        sortFilters.Add("Joel Greenblatt (ROC)");
        sortFilters.Add("Rule #1 (MOS)");
        sortFilters.Add("Rule #1 (MOS) R>=15%");
        sortFilters.Add("Rule #1 (MOS80)");
        sortFilters.Add("Rule #1 Factors");
        SortFilters=new ObservableCollection<String>(sortFilters);
      }
      public String SelectedSortFilter
      {
        get{return selectedSortFilter;}
        set{selectedSortFilter=value;base.OnPropertyChanged("SelectedSortFilter");}
      }
      public ObservableCollection<String> SortFilters
      {
        get;
        private set;
      }
      public ObservableCollection<ValuationModel> AllValuations
      {
        get;
        private set;
      }
      public String Title
      {
        get{return " CalcSticker ("+SelectedValuationDate+")";}
      }
// ******************************************************************************************************************************************************
      public override SaveParameters GetSaveParameters()
      {
        SaveParameters saveParams = new SaveParameters();
        saveParams.Add(new KeyValuePair<String, String>("Type", GetType().Namespace + "." + GetType().Name));
        saveParams.Add(new KeyValuePair<String, String>("SelectedValuationDate", selectedValuationDate));
        saveParams.Add(new KeyValuePair<String, String>("SelectedSortFilter", selectedSortFilter));

        return saveParams;
      }
      public override void SetSaveParameters(SaveParameters saveParameters)
      {
        try
        {
          selectedValuationDate = (from KeyValuePair<String, String> item in saveParameters where item.Key.Equals("SelectedValuationDate") select item).FirstOrDefault().Value;
          try{selectedSortFilter = (from KeyValuePair<String, String> item in saveParameters where item.Key.Equals("SelectedSortFilter") select item).FirstOrDefault().Value;}
          catch(Exception){;}
          if(null==selectedSortFilter)selectedSortFilter=sortFilters[0];
          Referer = saveParameters.Referer;
          base.OnPropertyChanged("SelectedSortFilter");
        }
        catch (Exception exception)
        {
          MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString()));
        }
      }
      public override bool CanPersist()
      {
        return true;
      }



// ******************************************************************************************************************************************************
// *************************************************************** T O O L T I P   C A L L O U T S ******************************************************
// ******************************************************************************************************************************************************
      public String PCFDescription
      {
        get
        {
          if(null== selectedItem || null==selectedItem.Symbol)return "No row selected.";
          return "(Price to Operating Cashflow): CurrentPrice/(Operating Cashflow/Shares Outstanding).";
        }
      }
      public String DividendYieldDescription
      {
        get
        {
          if(null== selectedItem || null==selectedItem.Symbol)return "No row selected.";
          return "DividendYield: Dividend Payments/Current Price.";
        }
      }
      public String MarketCapDescription
      {
        get
        {
          if(null== selectedItem || null==selectedItem.Symbol)return "No row selected.";
          return "MarketCap: Market Capitalization. Fundamentals.";
        }
      }
      public String EBITDescription
      {
        get
        {
          if(null== selectedItem || null==selectedItem.Symbol)return "No row selected.";
          return "EBIT: Earnings Before Interest and Taxes. Fundamentals.";
        }
      }
      public String AcquirersMultipleDescription
      {
        get
        {
          if(null== selectedItem || null==selectedItem.Symbol)return "No row selected.";
          return "Acquirers Multiple (Tobias Carlisle uses EV/OE and ranks to lowest).  This is ranked as the higher the rank the better.  If market capitalization < $200,000,00.00 rank will be set to zero.";
        }
      }
      public String OperatingEarningsDescription
      {
        get
        {
          if(null== selectedItem || null==selectedItem.Symbol)return "No row selected.";
          return "Tobias Carlisle : Revenue-(Cost of Goods Sold + Selling, General, and Administrative+Depreciation and Amortization)";
        }
      }
      public String AMRankDescription
      {
        get
        {
          if(null== selectedItem || null==selectedItem.Symbol)return "No row selected.";
          return "Acquirers Multiple (Tobias Carlisle) Rank based on Enterprise Value/Operating Earnings.  This is ranked as the higher the rank the better.";
        }
      }
      public String BetaDescription
      {
        get
        {
          if(null== selectedItem || null==selectedItem.Symbol)return "No row selected.";
          return "Beta:Covariance(stock,benchmark)/Variance(benchmark).  (<1.00 less volatile than market)(1.00=parity with market)(>1.00 more volatile than market)";
        }
      }
      public String DebtToEquityDescription
      {
        get
        {
          if(null== selectedItem || null==selectedItem.Symbol)return "No row selected.";
          return "Fundamental : DebtToEquity";
        }
      }
      public String CompanyDescription
      {
        get
        {
          if(null== selectedItem || null==selectedItem.Symbol)return "No row selected.";
          CompanyProfile companyProfile=CompanyProfileDA.GetCompanyProfile(selectedItem.Symbol);
          if(null==companyProfile || null==companyProfile.Description)return "No description found.";
          return companyProfile.Description;
        }
      }
      public String EarningsYieldDescription
      {
        get
        {
          if(null== selectedItem || null==selectedItem.Symbol)return "No row selected.";
          StringBuilder sb=new StringBuilder();
          sb.Append("EarningsYield:EBIT/EnterpriseValue");
          return sb.ToString();
        }
      }
      public String EnterpriseValueDescription
      {
        get
        {
          if(null== selectedItem || null==selectedItem.Symbol)return "No row selected.";
          StringBuilder sb=new StringBuilder();
          sb.Append("EnterpriseValue:Yahoo Finance (Key Statistics)");
          return sb.ToString();
        }
      }
      public String TLBRankROICDescription
      {
        get
        {
          if(null== selectedItem || null==selectedItem.Symbol)return "No row selected.";
          StringBuilder sb=new StringBuilder();
          sb.Append("TLBRankROIC:Max(Rank[ROIC]+Rank[EarningsYield]).  The higher the rank, the better.");
          return sb.ToString();
        }
      }
      public String TLBRankROCDescription
      {
        get
        {
          if(null== selectedItem || null==selectedItem.Symbol)return "No row selected.";
          StringBuilder sb=new StringBuilder();
          sb.Append("TLBRankROC:Max(Rank[ROC]+Rank[EarningsYield]) where ROC=EBIT/(Net Fixed Assets + Working Capital)  Note: Net PPE = Net Fixed Assets.  The higher the rank, the better.");
          return sb.ToString();
        }
      }
// ************************************************************************************************************************************************************************************
// ************************************************************************************************************************************************************************************
// ************************************************************************************************************************************************************************************
      public ObservableCollection<MenuItem> MenuItems
      {
        get
        {
          ObservableCollection<MenuItem> collection = new ObservableCollection<MenuItem>();
          collection.Add(new MenuItem() { Text = "Display Bollinger Band", MenuItemClickedCommand = DisplayBollingerBand, StaysOpenOnClick = false });
          collection.Add(new MenuItem() { Text = "Display Dividend History", MenuItemClickedCommand = DisplayDividendHistory, StaysOpenOnClick = false });
          collection.Add(new MenuItem() { Text = "Display Proforma Dividend Risk", MenuItemClickedCommand = DisplayProformaDividendRisk, StaysOpenOnClick = false });
					collection.Add(new MenuItem() { Text = "Display Sticker Valuation", MenuItemClickedCommand = DisplayStickerValuation, StaysOpenOnClick = false });
					collection.Add(new MenuItem() { Text = "Display Historical", MenuItemClickedCommand = DisplayHistorical, StaysOpenOnClick = false });
          collection.Add(new MenuItem() { Text = "Display Stochastics", MenuItemClickedCommand = DisplayStochastic, StaysOpenOnClick = false });
          collection.Add(new MenuItem() { Text = "Display Relative Strength", MenuItemClickedCommand=DisplayRelativeStrength, StaysOpenOnClick = false });
          collection.Add(new MenuItem() { Text = "Display MACD", MenuItemClickedCommand = DisplayMACD, StaysOpenOnClick = false });
          collection.Add(new MenuItem() { Text = "Display Moving Average", MenuItemClickedCommand = DisplayMovingAverage, StaysOpenOnClick = false });
          collection.Add(new MenuItem() { Text = "Display Price History", MenuItemClickedCommand = DisplayPriceHistory, StaysOpenOnClick = false });
					collection.Add(new MenuItem() { Text = "Display DCF Valuation", MenuItemClickedCommand = DisplayDCFValuation, StaysOpenOnClick = false });
					collection.Add(new MenuItem() { Text = "Display Analyst Ratings", MenuItemClickedCommand = DisplayAnalystRatings, StaysOpenOnClick = false });
					collection.Add(new MenuItem() { Text = "Display Headlines", MenuItemClickedCommand = DisplayHeadlines, StaysOpenOnClick = false });
					collection.Add(new MenuItem() { Text = "Display SEC Filings", MenuItemClickedCommand = DisplaySECFilings, StaysOpenOnClick = false });
          collection.Add(new MenuItem() { Text = "Add to Watchlist", MenuItemClickedCommand = AddToWatchList, StaysOpenOnClick = false });
          collection.Add(new MenuItem() { Text = "Remove from Watchlist", MenuItemClickedCommand = RemoveFromWatchList, StaysOpenOnClick = false });
          collection.Add(new MenuItem() { Text = "Remove Valuation", MenuItemClickedCommand = RemoveValuation, StaysOpenOnClick = false });
          return collection;
        }
      }
// ********************************************************************************************************************************************************************
// ****************************************************************** I  C  O  M  M  A  N  D **************************************************************************
// ********************************************************************************************************************************************************************
      public ICommand DisplayProformaDividendRisk
      {
        get
        {
          if (proformaDividendRiskCommand == null)
          {
            proformaDividendRiskCommand = new RelayCommand(param =>
            {
              SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.DividendRiskParityViewModel,SelectedSymbol," + selectedItem.Symbol + "");
              saveParams.Referer = this;
              WorkspaceInstantiator.Invoke(saveParams);
            }, param => { return null != selectedItem && null != selectedItem.Symbol; });
          }
          return proformaDividendRiskCommand;
        }
      }
      public ICommand DisplayHistorical
      {
        get
        {
          if (displayHistoricalCommand == null)
          {
            displayHistoricalCommand = new RelayCommand(param => 
            {
              SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.HistoricalViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All}");
              saveParams.Referer=this;
              WorkspaceInstantiator.Invoke(saveParams);
            }, param => { return null != selectedItem && null != selectedItem.Symbol; });
          }
          return displayHistoricalCommand;
        }
      }
      public ICommand DisplayDividendHistory
      {
        get
        {
          if (dividendHistoryCommand == null)
          {
            dividendHistoryCommand = new RelayCommand(param => 
            {
              SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.DividendHistoryViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All}");
              saveParams.Referer=this;
              WorkspaceInstantiator.Invoke(saveParams);
            }, param => { return null != selectedItem && null != selectedItem.Symbol; });
          }
          return dividendHistoryCommand;
        }
      }
      public ICommand DisplaySECFilings
      {
        get
        {
          if (null == displaySECFilingsCommand)
          {
            displaySECFilingsCommand = new RelayCommand(param =>
            {
              SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.SECFilingViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,Valuations");
              saveParams.Referer=this;
              WorkspaceInstantiator.Invoke(saveParams);
            }, param => { return null != selectedItem && null!=selectedItem.Symbol; });
          }
          return displaySECFilingsCommand;
        }
      }
      public ICommand DisplayHeadlines
      {
        get
        {
          if (null == displayHeadlinesCommand)
          {
            displayHeadlinesCommand = new RelayCommand(param =>
            {
              SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.HeadlinesViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,Valuations");
              saveParams.Referer=this;
              WorkspaceInstantiator.Invoke(saveParams);
            }, param => { return null != selectedItem && null!=selectedItem.Symbol; });
          }
          return displayHeadlinesCommand;
        }
      }
      public ICommand DisplayAnalystRatings
      {
        get
        {
          if (null == displayAnalystRatingsCommand)
          {
            displayAnalystRatingsCommand = new RelayCommand(param =>
            {
              SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.AnalystRatingsViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All}");
              saveParams.Referer=this;
              WorkspaceInstantiator.Invoke(saveParams);
            }, param => { return null != selectedItem && null!=selectedItem.Symbol; });
          }
          return displayAnalystRatingsCommand;
        }
      }
      public ICommand DisplayStickerValuation
      {
        get
        {
          if (null == stickerValuationCommand)
          {
            stickerValuationCommand = new RelayCommand(param =>
            {
              SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.StickerPriceViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All}");
              saveParams.Referer=this;
              WorkspaceInstantiator.Invoke(saveParams);
            }, param => { return null != selectedItem && null!=selectedItem.Symbol; });
          }
          return stickerValuationCommand;
        }
      }
      public ICommand DisplayDCFValuation
      {
        get
        {
          if (null == dcfValuationCommand)
          {
            dcfValuationCommand = new RelayCommand(param =>
            {
              SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.DCFValuationViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All}");
              saveParams.Referer=this;
              WorkspaceInstantiator.Invoke(saveParams);
            }, param => { return null != selectedItem && null!=selectedItem.Symbol; });
          }
          return dcfValuationCommand;
        }
      }
      public ICommand RemoveValuation
      {
        get
        {
          if (null == removeValuationCommand)
          {
            removeValuationCommand = new RelayCommand(param =>
            {
              this.RemoveFromValuationCommand();
            }, param => { return null != selectedItem && null!=selectedItem.Symbol; });
          }
          return removeValuationCommand;
        }
      }
      public ICommand AddToWatchList
      {
        get
        {
          if (addToWatchListCommand == null)
          {
            addToWatchListCommand = new RelayCommand(param => this.AddToWatchListCommand(), 
              param => 
              {
                if(null==selectedItem || null==selectedItem.Symbol)return false;
                if (WatchListDA.IsInWatchList(selectedItem.Symbol)) return false;
                return true;
              });
          }
          return addToWatchListCommand;
        }
      }
      public ICommand RemoveFromWatchList
      {
        get
        {
          if (removeFromWatchListCommand == null)
          {
            removeFromWatchListCommand = new RelayCommand(param => this.RemoveFromWatchListCommand(), 
              param => 
              {
                if(null==selectedItem || null==selectedItem.Symbol)return false;
                if (!WatchListDA.IsInWatchList(selectedItem.Symbol)) return false;
                return true;
              });
          }
          return removeFromWatchListCommand;
        }
      }
      public ICommand DisplayBollingerBand
      {
        get
        {
          if (bollingerBandCommand == null)
          {
            bollingerBandCommand = new RelayCommand(param => this.DisplayBollingerBandCommand(), 
              param => { return null != selectedItem && null!=selectedItem.Symbol; });
          }
          return bollingerBandCommand;
        }
      }
      public ICommand DisplayMovingAverage
      {
        get
        {
          if (movingAverageCommand == null)
          {
            movingAverageCommand = new RelayCommand(param => this.DisplayMovingAverageCommand(), param => { return null != selectedItem && null != selectedItem.Symbol; });
          }
          return movingAverageCommand;
        }
      }
      public ICommand DisplayStochastic
      {
        get
        {
          if (stochasticsCommand == null)
          {
            stochasticsCommand = new RelayCommand(param => this.DisplayStochasticCommand(),
              param => { return null != selectedItem && null != selectedItem.Symbol; });
          }
          return stochasticsCommand;
        }
      }
// ********************************************************************************************************************************************************************
// ********************************************************************************************************************************************************************
// ********************************************************************************************************************************************************************
      public void RemoveFromValuationCommand()
      {
        ValuationDA.RemoveValuationBySymbol(selectedItem.Symbol,DateTime.Parse(selectedItem.ValuationDate));
        base.OnPropertyChanged("SelectedValuationDate");
      }
      public void AddToWatchListCommand()
      {
        if (WatchListDA.IsInWatchList(selectedItem.Symbol))
        {
          System.Windows.MessageBox.Show("'"+selectedItem.Symbol+"' is already in watchlist","Info", MessageBoxButton.OK,  MessageBoxImage.Information);
          return;
        }
        if (!WatchListDA.AddToWatchList(selectedItem.Symbol))
        {
          System.Windows.MessageBox.Show("Error adding '"+selectedItem.Symbol+"' to watchlist","Warning", MessageBoxButton.OK,  MessageBoxImage.Warning);
        }
        else
        {
          System.Windows.MessageBox.Show("Added '"+selectedItem.Symbol+"'","Success", MessageBoxButton.OK,  MessageBoxImage.Information);
        }
      }
      public void RemoveFromWatchListCommand()
      {
        if (!WatchListDA.IsInWatchList(selectedItem.Symbol))
        {
          System.Windows.MessageBox.Show("'"+selectedItem.Symbol+"' is not in watchlist","Info", MessageBoxButton.OK,  MessageBoxImage.Information);
          return;
        }
        if (!WatchListDA.RemoveFromWatchList(selectedItem.Symbol))
        {
          System.Windows.MessageBox.Show("Error removing '"+selectedItem.Symbol+"' from watchlist","Warning", MessageBoxButton.OK,  MessageBoxImage.Warning);
        }
        else
        {
          System.Windows.MessageBox.Show("Removed '"+selectedItem.Symbol+"'","Success", MessageBoxButton.OK,  MessageBoxImage.Information);
        }
      }
      public void DisplayBollingerBandCommand()
      {
        SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.BollingerBandViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All},SelectedDayCount,180");
        saveParams.Referer=this;
        WorkspaceInstantiator.Invoke(saveParams);
      }

      public void DisplayMovingAverageCommand()
      {
        SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.MovingAverageViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All},SelectedDayCount,360");
        saveParams.Referer = this;
        WorkspaceInstantiator.Invoke(saveParams);
      }
      public void DisplayStochasticCommand()
      {
        SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.StochasticsViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All},SelectedDayCount,180");
        saveParams.Referer=this;
        WorkspaceInstantiator.Invoke(saveParams);
      }
      public ICommand DisplayRelativeStrength
      {
        get
        {
          if (relativeStrengthCommand == null)
          {
            relativeStrengthCommand = new RelayCommand(param => this.DisplayRelativeStrengthCommand(), 
              param => { return null != selectedItem && null!=selectedItem.Symbol; });
          }
          return relativeStrengthCommand;
        }
      }
      public void DisplayRelativeStrengthCommand()
      {
        SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.RSIViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All},SelectedDayCount,60,SelectedRSIDayCount,14");
        saveParams.Referer=this;
        WorkspaceInstantiator.Invoke(saveParams);
      }
      public ICommand DisplayMACD
      {
        get
        {
          if (macdCommand == null)
          {
            macdCommand = new RelayCommand(param => this.DisplayMACDCommand(), 
              param => { return null != selectedItem && null!=selectedItem.Symbol; });
          }
          return macdCommand;
        }
      }
      public void DisplayMACDCommand()
      {
        SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.MACDViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All},SelectedDayCount,180");
        saveParams.Referer=this;
        WorkspaceInstantiator.Invoke(saveParams);
      }
      public ICommand DisplayPriceHistory
      {
        get
        {
          if (priceHistoryCommand == null)
          {
            priceHistoryCommand = new RelayCommand(param => this.DisplayPriceHistoryCommand(), 
              param => { return null != selectedItem && null!=selectedItem.Symbol; });
          }
          return priceHistoryCommand;
        }
      }
      public void DisplayPriceHistoryCommand()
      {
        SaveParameters saveParams = SaveParameters.Parse("Type,TradeBlotter.ViewModels.PricingViewModel,SelectedSymbol," + selectedItem.Symbol + ",SelectedWatchList,{All},SelectedDayCount,180");
        saveParams.Referer=this;
        WorkspaceInstantiator.Invoke(saveParams);
      }
// **************************************************************************************************************************************************
// **************************************************************************************************************************************************
// **************************************************************************************************************************************************
      private void CreateAllValuations()
      {
        try
        {
          if (null == selectedValuationDate) return;
          BusyIndicator = true;
          Task workerTask = Task.Factory.StartNew(() =>
          {
            Valuations valuations = ValuationDA.GetValuation(DateTime.Parse(selectedValuationDate));
            List<ValuationModel> selectedValuations=ApplySortFilter(valuations,selectedSortFilter);
            this.AllValuations = new ObservableCollection<ValuationModel>(selectedValuations);
          });
          workerTask.ContinueWith((continuation) =>
          {
            BusyIndicator = false;
            base.OnPropertyChanged("RowCount");
            base.OnPropertyChanged("AllValuations");
          });
        }
        catch (Exception exception)
        {
          MDTrace.WriteLine(LogLevel.DEBUG,exception);
        }
      }
// *******************************************************************************************************************************************************
// ******************************************************************************** S O R T I N G ********************************************************
// *******************************************************************************************************************************************************
      private List<ValuationModel> ApplySortFilter(Valuations valuations, String sortFilter)
      {
        List<Valuation> sortedList;
        switch(sortFilter)
        {
          case "Acquirers Multiple" :
            sortedList=valuations.OrderByDescending(x=>x.AMRank).ThenByDescending(y=>y.TLBRankROIC).ThenByDescending(z=>z.TLBRankROC).ToList(); 
            return (from valuation in sortedList select new ValuationModel(valuation,valuations.ValuationDate)).ToList();     
            break;
          case "Joel Greenblatt (ROIC)" :
            sortedList=valuations.OrderByDescending(x=>x.TLBRankROIC).ThenByDescending(y=>y.TLBRankROC).ThenByDescending(z=>z.TLBRankROC).ToList(); 
            return (from valuation in sortedList select new ValuationModel(valuation,valuations.ValuationDate)).ToList();     
            break;
          case "Joel Greenblatt (ROC)" :
            sortedList=valuations.OrderByDescending(x=>x.TLBRankROC).ThenByDescending(y=>y.TLBRankROIC).ThenByDescending(z=>z.TLBRankROC).ToList(); 
            return (from valuation in sortedList select new ValuationModel(valuation,valuations.ValuationDate)).ToList();     
            break;
          case "Rule #1 (MOS)":
            sortedList=(from valuation in valuations where valuation.Bargain.Equals(true) && valuation.LatestROICDate.Year>=valuations.ValuationDate.Year  && valuation.DebtLoad.Equals("Pass") select valuation).OrderByDescending(s=>s.LatestROICDate).OrderByDescending(t=>t.ROICSlope).OrderByDescending(u=>u.AverageROIC).ThenByDescending(v=>v.AverageEPSGrowth).ThenByDescending(w=>w.AverageRevenueGrowth).ThenByDescending(x=>x.AverageFreeCashflowGrowth).ThenByDescending(y=>y.AverageEquityGrowth).ThenBy(z=>z.SharesOutstanding).ThenBy(za=>za.MarketCap).ToList();
            return (from valuation in sortedList select new ValuationModel(valuation, valuations.ValuationDate)).ToList();     
            break;
          case "Rule #1 (MOS) R>=15%":
            sortedList = (from valuation in valuations where valuation.Bargain.Equals(true) && valuation.AverageROIC>=.15 && valuation.LatestROICDate.Year >= valuations.ValuationDate.Year && valuation.DebtLoad.Equals("Pass") select valuation).OrderByDescending(s => s.LatestROICDate).OrderByDescending(t => t.ROICSlope).OrderByDescending(u => u.AverageROIC).ThenByDescending(v => v.AverageEPSGrowth).ThenByDescending(w => w.AverageRevenueGrowth).ThenByDescending(x => x.AverageFreeCashflowGrowth).ThenByDescending(y => y.AverageEquityGrowth).ThenBy(z => z.SharesOutstanding).ThenBy(za => za.MarketCap).ToList();
            return (from valuation in sortedList select new ValuationModel(valuation, valuations.ValuationDate)).ToList();
            break;
          case "Rule #1 (MOS80)":
            sortedList = (from valuation in valuations where valuation.Bargain80.Equals(true) && valuation.LatestROICDate.Year>=valuations.ValuationDate.Year && valuation.DebtLoad.Equals("Pass") select valuation).OrderByDescending(s=>s.LatestROICDate).OrderByDescending(t => t.ROICSlope).OrderByDescending(u => u.AverageROIC).ThenByDescending(v => v.AverageEPSGrowth).ThenByDescending(w => w.AverageRevenueGrowth).ThenByDescending(x => x.AverageFreeCashflowGrowth).ThenByDescending(y => y.AverageEquityGrowth).ThenBy(z => z.SharesOutstanding).ThenBy(za => za.MarketCap).ToList();
            return (from valuation in sortedList select new ValuationModel(valuation, valuations.ValuationDate)).ToList();
            break;
          case "Rule #1 Factors":
            sortedList = (from valuation in valuations where valuation.LatestROICDate.Year>=valuations.ValuationDate.Year select valuation).OrderByDescending(s=>s.LatestROICDate).OrderByDescending(t=>t.ROICSlope).OrderByDescending(u => u.AverageROIC).ThenByDescending(v => v.AverageEPSGrowth).ThenByDescending(w => w.AverageRevenueGrowth).ThenByDescending(x => x.AverageFreeCashflowGrowth).ThenByDescending(y => y.AverageEquityGrowth).ThenBy(z => z.SharesOutstanding).ToList();
            return (from valuation in sortedList select new ValuationModel(valuation, valuations.ValuationDate)).ToList();
            break;
          case "None":
          default: return (from valuation in valuations select new ValuationModel(valuation, valuations.ValuationDate)).ToList();
        }
      }


// ********************************************************************************************************************************************************
      public bool BusyIndicator
      {
        get { return busyIndicator; }
        set { busyIndicator = value; base.OnPropertyChanged("BusyIndicator"); }
      }
      public String BusyContent
      {
        get { return "Loading Valuations..."; }
      }

      public String SaveDocument
      {
        get { return saveDocument; }
        set { saveDocument = value; base.OnPropertyChanged("SaveDocument"); }
      }
      private void Save()
      {
        SaveDocument = "Valuations_"+(saveCount++)+".xls";
      }
      private bool CanSave
      {
        get { return true; }
      }
      public ICommand SaveCommand
      {
        get
        {
          if (saveCommand == null)
          {
            saveCommand = new RelayCommand(param => this.Save(), param => this.CanSave);
          }
          return saveCommand;
        }
      }
      public String SelectedValuationDate
      {
        get { return selectedValuationDate; }
        set { selectedValuationDate = value; base.OnPropertyChanged("SelectedValuationDate"); }
      }
      public String RowCount
      {
        get { return null == this.AllValuations ? Constants.CONST_DASHES : this.AllValuations.Count.ToString(); }
        set { ;}
      }
      public List<String> ValuationDates
      {
        get
        {
          List<String> valuationDatesStr = new List<String>();
          List<DateTime> valuationDates = ValuationDA.GetValuationDates();
          foreach (DateTime valuationDate in valuationDates)
          {
            valuationDatesStr.Add(Utility.DateTimeToStringMMHDDHYYYY(valuationDate));
          }
          return valuationDatesStr;
        }
      }
      public ValuationModel SelectedItem
      {
        get
        {
          return selectedItem;
        }
        set
        {
          selectedItem = value;
        }
      }
   }
}
