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

namespace MarketData.MarketDataModel
{
  public class Enhancements
  {
    public bool DebtLoad { get; set; }
    public double ROIC { get; set; }
    public double ROICGrowth { get; set; }
    public double EPSGrowth { get; set; }
    public double RevenueGrowth { get; set; }
    public double BVPS { get; set; }
    public double PBVPS { get; set; }
    public double EPS { get; set; }
    public double PE { get; set; }
    public double PEG { get; set; }
    public double MOS { get; set; }
    public double MOS80 { get; set; }
    public double IntrinsicValue { get; set; }           // Benjamin Graham original intrinsic value
    public double IntrinsicValueRevised { get; set; }  // Benjamin Graham revised instrinsic value (uses the yield on 20 year corporate bonds
    public double RGVIntrinsic { get; set; }
    public double RGVIntrinsicRevised { get; set; }
    public Enhancements()
    {
      DebtLoad = false;
      ROIC = double.NaN;
      ROICGrowth = double.NaN;
      EPSGrowth = double.NaN;
      RevenueGrowth = double.NaN;
      BVPS = double.NaN;
      PBVPS = double.NaN;
      EPS = double.NaN;
      PE = double.NaN;
      PEG = double.NaN;
      MOS = double.NaN;
      MOS80 = double.NaN;
      IntrinsicValue = double.NaN;
      RGVIntrinsic = double.NaN;
      IntrinsicValueRevised = double.NaN;
      RGVIntrinsicRevised = double.NaN;
    }
  }
  public class DCFValuation
  {
    public const double MARKET_RETURN=.11;
    private String symbol;
    private double wacc=double.NaN;
    private double costOfEquity=double.NaN;
    private double costOfDebt=double.NaN;
    private double marketValueOfEquity=double.NaN;
    private double marketValueOfDebt = double.NaN;
    private double totalCapitalInvested = double.NaN;
    private double corporateTaxRate = double.NaN;
    private double beta = double.NaN;
    private double riskFreeRate = double.NaN;
    private double interestExpense = double.NaN;
    private double interestRate = double.NaN;
    private double totalDebt = double.NaN;
    private double outstandingShares = double.NaN;
    private double freeCashflowGrowth = double.NaN;
    private double presentValue = double.NaN;
    private double stockPriceValuation = double.NaN;
    private double marketReturn=MARKET_RETURN;
    private Price currentPrice;
    private Cashflows cashflows = new Cashflows();
    private ReturnItems returnItems = new ReturnItems();
    private Enhancements enhancements = new Enhancements();
    private String message;
    private bool useMarketReturn = false;
    public bool success = false;

    public bool UseMarketReturn
    {
      get { return useMarketReturn; }
      set { useMarketReturn = value; if (useMarketReturn)marketReturn = 0.00; else marketReturn = MARKET_RETURN; }
    }
    public String Symbol
    {
      get { return symbol; }
      set { symbol = value; }
    }
    public Price CurrentPrice
    {
      get { return currentPrice; }
      set { currentPrice = value; }
    }
    public double WACC
    {
      get { return wacc; }
      set { wacc = value; }
    }
    public double CostOfEquity
    {
      get { return costOfEquity; }
      set { costOfEquity = value; }
    }
    public double CostOfDebt
    {
      get { return costOfDebt; }
      set { costOfDebt = value; }
    }
    public double MarketValueOfEquity
    {
      get { return marketValueOfEquity; }
      set { marketValueOfEquity = value; }
    }
    public double MarketValueOfDebt
    {
      get { return marketValueOfDebt; }
      set { marketValueOfDebt = value; }
    }
    public double TotalCapitalInvested
    {
      get { return totalCapitalInvested; }
      set { totalCapitalInvested = value; }
    }
    public double CorporateTaxRate
    {
      get { return corporateTaxRate; }
      set { corporateTaxRate = value; }
    }
    public double Beta
    {
      get { return beta; }
      set { beta = value; }
    }
    public double RiskFreeRate
    {
      get { return riskFreeRate; }
      set { riskFreeRate = value; }
    }
    public double InterestExpense
    {
      get { return interestExpense; }
      set { interestExpense = value; }
    }
    public double InterestRate
    {
      get { return interestRate; }
      set { interestRate = value; }
    }
    public double TotalDebt
    {
      get { return totalDebt; }
      set { totalDebt = value; }
    }
    public double FreeCashflowGrowth
    {
      get { return freeCashflowGrowth; }
      set { freeCashflowGrowth = value; }
    }
    public double OutstandingShares
    {
      get { return outstandingShares; }
      set { outstandingShares = value; }
    }
    public ReturnItems ReturnItems
    {
      get { return returnItems; }
    }
    public Cashflows Cashflows
    {
      get { return cashflows; }
    }
    public double StockPriceValuation
    {
      get { return stockPriceValuation; }
      set { stockPriceValuation = value; }
    }
    public double PresentValue
    {
      get { return presentValue; }
      set { presentValue = value; }
    }
    public double MarketReturn
    {
      get { return marketReturn; }
      set { marketReturn = value; }
    }
    public String Message
    {
      get { return message; }
      set { message = value; }
    }
    public bool Success
    {
      get { return success; }
      set { success = value; }
    }
    public Enhancements Enhancements
    {
      get { return enhancements; }
      set { enhancements = value; }
    }
    public override String ToString()
    {
      StringBuilder sb = new StringBuilder();
      sb.Append(Symbol).Append(",");
      sb.Append(Success).Append(",");
      if (!Success)
      {
        sb.Append(",");
        sb.Append(",");
        sb.Append(",");
        sb.Append(",");
        sb.Append(",");
        sb.Append(",");
        sb.Append(",");
        sb.Append(",");
        sb.Append(",");
        sb.Append(",");
        sb.Append(",");
        sb.Append(",");
        sb.Append(",");
        sb.Append(",");
        sb.Append(",");
        sb.Append(",");
        sb.Append(",");
        sb.Append(",");
        sb.Append(",");

        sb.Append(",");
        sb.Append(",");
        sb.Append(",");
        sb.Append(",");
        sb.Append(",");
        sb.Append(",");
        sb.Append(",");
        sb.Append(",");
        sb.Append(",");
        sb.Append(",");
        sb.Append(",");
        sb.Append(",");
        sb.Append(",");
        sb.Append(",");

        sb.Append(Message);
      }
      else
      {
        sb.Append(WACC).Append(",");
        sb.Append(MarketReturn).Append(",");
        sb.Append(CostOfEquity).Append(",");
        sb.Append(CostOfDebt).Append(",");
        sb.Append(MarketValueOfEquity).Append(",");
        sb.Append(MarketValueOfDebt).Append(",");
        sb.Append(TotalCapitalInvested).Append(",");
        sb.Append(CorporateTaxRate).Append(",");
        sb.Append(Beta).Append(",");
        sb.Append(RiskFreeRate).Append(",");
        sb.Append(InterestExpense).Append(",");
        sb.Append(InterestRate).Append(",");
        sb.Append(TotalDebt).Append(",");
        sb.Append(OutstandingShares).Append(",");
        sb.Append(FreeCashflowGrowth).Append(",");
        sb.Append(PresentValue).Append(",");
        sb.Append(StockPriceValuation).Append(",");
        if (null == currentPrice)
        {
          sb.Append(",");
          sb.Append(",");
        }
        else
        {
          sb.Append(CurrentPrice.Close).Append(",");
          sb.Append(Utility.DateTimeToStringMMSDDSYYYY(CurrentPrice.Date)).Append(",");
        }

        sb.Append(Enhancements.DebtLoad?"PASS":"FAIL").Append(",");
        sb.Append(Enhancements.ROIC).Append(",");
        sb.Append(Enhancements.ROICGrowth).Append(",");
        sb.Append(Enhancements.EPSGrowth).Append(",");
        sb.Append(Enhancements.RevenueGrowth).Append(",");
        sb.Append(Enhancements.BVPS).Append(",");
        sb.Append(Enhancements.PBVPS).Append(",");
        sb.Append(Enhancements.EPS).Append(",");
        sb.Append(Enhancements.PEG).Append(",");
        sb.Append(Enhancements.MOS).Append(",");
        sb.Append(Enhancements.MOS80).Append(",");
        sb.Append(Enhancements.IntrinsicValue).Append(",");
        sb.Append(Enhancements.IntrinsicValueRevised).Append(",");
        sb.Append(Enhancements.RGVIntrinsic).Append(",");
        sb.Append(Enhancements.RGVIntrinsicRevised).Append(",");

        sb.Append(Message);
      }
      return sb.ToString();
    }
    public static String Header
    {
      get
      {
        StringBuilder sb = new StringBuilder();
        sb.Append("SYMBOL,STATUS,WACC,MARKET_RETURN,COST_OF_EQUITY,COST_OF_DEBT,MARKET_VALUE_OF_EQUITY,MARKET_VALUE_OF_DEBT,TOTAL_CAPITAL_INVESTED,CORPORATE_TAX_RATE,BETA,RISK_FREE_RATE,INTEREST_EXPENSE,INTEREST_RATE,TOTAL_DEBT,OUTSTANDING_SHARES,FREE_CASHFLOW_GROWTH,PRESENT_VALUE,STOCK_PRICE_VALUATION,CURRENT_STOCK_PRICE,PRICING_DATE,");
        sb.Append("DEBT_LOAD,");
        sb.Append("ROIC_GROWTH,");
        sb.Append("EPS_GROWTH,");
        sb.Append("REVENUE_GROWTH,");
        sb.Append("BVPS,");
        sb.Append("PBVPS,");
        sb.Append("EPS,");
        sb.Append("PEG,");
        sb.Append("MOS,");
        sb.Append("MOS80,");
        sb.Append("INTRINSIC_VALUE,");
        sb.Append("INSTRINSIC_VALUE_REVISED,");
        sb.Append("RGV_INSTRINSIC_VALUE,");
        sb.Append("RGV_INSTRINSIC_VALUE_REVISED,");
        sb.Append("MESSAGE");
        return sb.ToString();
      }
    }
  }
}
