using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using MarketData.Utils;

namespace MarketData.MarketDataModel
{

// ********************************************************* V A L U A T I O N S ****************************************************
  public class Valuations : List<Valuation>
  {
    public Valuations()
    {
      ValuationDate = DateTime.Now;
    }
    public Valuations(List<Valuation> valuations)
    {
      foreach(Valuation valuation in valuations)Add(valuation);
    }
    public DateTime ValuationDate{get;set;}
  }                                                                                 
  public class Valuation
  {
    public String Symbol { get; set; }
    public String Company { get; set; }
    public double Beta90 { get; set; }
    public double Beta720 { get; set; }
    public DateTime NextEarningsDate { get; set; }
    public double LongTermDebt { get; set; }
    public double Revenue { get; set; }
    public String DebtLoad { get; set; }
    public double AverageROIC { get; set; }
    public double LatestROIC { get; set; }
    public double LatestROC{get;set;}   // Return on Capital = EBIT / (Net Fixed Assets + Working Capital)  where Net Fixed Assets = Net Property, Plant, and Equipment
    public double ROICSlope{get;set;}
    public String ROICDates{get;set;}
    public DateTime LatestROICDate{get{return null==ROICDates?DateTime.MinValue:DateTime.Parse(Utility.BetweenString(ROICDates,"-",null));}}
    public String BVPSDates { get; set; }
    public double AverageEquityGrowth { get; set; }
    public double AverageEquityGrowth2Y { get; set; }
    public double AverageEquityGrowth4Y { get; set; }
    public String EPSDates { get; set; }
    public double AverageEPSGrowth { get; set; }
    public double AverageEPSGrowth2Y { get; set; }
    public double AverageEPSGrowth4Y { get; set; }
    public String RevenueDates { get; set; }
    public double AverageBVPSGrowth { get; set; }
    public double AverageRevenueGrowth { get; set; }
    public double AverageRevenueGrowth2Y { get; set; }
    public double AverageRevenueGrowth4Y { get; set; }
    public double AverageFreeCashflowGrowth { get; set; }
    public double AverageOperatingCashflow { get; set; }
    public double AverageWorkingCapital { get; set; }
    public double BVPS { get; set; }
    public double PBVPS { get; set; }  // price to book
    public double EPS { get; set; }
    public double PE { get; set; }
    public double PExPBVPS
    {
      get{if(PE<0||PBVPS<0)return double.NaN; else return PE*PBVPS;}
    }
    public double PCF(double price=double.NaN)
    {
      if(double.IsNaN(price))price=LatestPrice;
      if(0==LatestPrice)return 0.00;
      if(0==SharesOutstanding||double.IsNaN(OperatingCashflow)||0==OperatingCashflow||double.IsNaN(SharesOutstanding))return double.NaN;
      return LatestPrice/(OperatingCashflow/SharesOutstanding);
    }
    //public double PCF
    //{
    //  get
    //  {
    //    if(0==LatestPrice)return 0.00;
    //    if(0==SharesOutstanding||double.IsNaN(OperatingCashflow)||0==OperatingCashflow||double.IsNaN(SharesOutstanding))return double.NaN;
    //    return LatestPrice/(OperatingCashflow/SharesOutstanding);
    //  }
    //}
    public double PEG { get; set; }
    public double ImpliedEarningsGrowth { get; set; }  // derived from (PE/PEG)/100.00
    public double LowPE { get; set; }
    public double TrailingPE { get; set; }
    public double AverageLowTrailing { get; set; }
    public double CurrentStockEstimatePrice { get; set; }
    public double PriceEstimate10Y { get; set; }
    public double TodaysPriceForRequiredReturn { get; set; }
    public double MOS { get; set; }
    public double MOS80 { get; set; }
    public double IntrinsicValue { get; set; } // Benjamin Graham original intrinsic value
    public double FundamentalValue{get;set;}  // Benjamin Graham fundamental value
    public double NetCurrentAssetValuePerShare{get;set;} // Benjamin Graham's net current asset value per share
    public double RGV { get; set; }
    public double LatestPrice { get; set; }
    public double UpsidePcnt { get; set; }
    public double DownsidePcnt { get; set; }
    public double MeanTargetPrice { get; set; }
    public double LowTargetPrice { get; set; }
    public double HighTargetPrice { get; set; }
    public double MarketCap{get;set;}
    public double EarningsYield{get;set;}  // derived from EBIT/EnterpriseValue
    public double EBIT{get;set;}
    public double DebtToEquity{get;set;}
    public double EnterpriseValue{get;set;}
    public double TLBRankROIC{get;set;}
    public double TLBRankROC{get;set;}
    public double AMRank{get;set;}       // AcquirersMultiple Rank
    public double OperatingEarnings{get;set;}  // Revenue-(CostOfGoodsSold+Selling, General, and Administrative+Depreciation and Amortization)
    public double AcquirersMultiple{get;set;}  // in the book "The Acquirers Multiple" Carlisle divides Enterprise Value by Operating Earnings to arrive at this value and then ranks (lowest best).  I do opposite, operating earnings / enterprise value and then rank highest
    public bool Bargain { get; set; }
    public bool Bargain80 { get; set; }
    public bool SEC13{get;set;}
    public DateTime SEC13FilingDate{get;set;}
    public String Sector{get;set;}
    public String Industry{get;set;}
    public ReturnItems BVPSItems { get; set; }
    public double DividendYield{get;set;}
    public double OperatingCashflow{get;set;}
    public double SharesOutstanding{get;set;}
    public DateTime Modified { get; set; }
  }
  public class ValuationsByROIC : IComparer<Valuation>
  {
    public int Compare(Valuation v1,Valuation v2)
    {
      if(double.IsNaN(v1.LatestROIC)&&double.IsNaN(v2.LatestROIC))return 0;
      else if(double.IsNaN(v1.LatestROIC))return -1;
      else if(double.IsNaN(v2.LatestROIC))return 1;
      return v1.LatestROIC.CompareTo(v2.LatestROIC);
    }
  }
  public class ValuationsByROC : IComparer<Valuation>
  {
    public int Compare(Valuation v1,Valuation v2)
    {
      if(double.IsNaN(v1.LatestROC)&&double.IsNaN(v2.LatestROC))return 0;
      else if(double.IsNaN(v1.LatestROC))return -1;
      else if(double.IsNaN(v2.LatestROC))return 1;
      return v1.LatestROC.CompareTo(v2.LatestROC);
    }
  }
  public class ValuationsByEarningsYield : IComparer<Valuation>
  {
    public int Compare(Valuation v1,Valuation 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 ValuationsByAcquirersMultiple : IComparer<Valuation>
  {
    public int Compare(Valuation v1,Valuation v2)
    {
      if(double.IsNaN(v1.AcquirersMultiple)&&double.IsNaN(v2.AcquirersMultiple))return 0;
      else if(double.IsNaN(v1.AcquirersMultiple))return -1;
      else if(double.IsNaN(v2.AcquirersMultiple))return 1;
      if(v1.AcquirersMultiple.Equals(v2.AcquirersMultiple))return 0;
      if(v1.AcquirersMultiple<v2.AcquirersMultiple)return 1;
      else return -1;
    }
  }
}
