using System;
using System.Text;
using MarketData.Utils;

namespace MarketData.MarketDataModel
{
  public class IncomeStatement
  {
    public enum PeriodType { Annual=0,Quarterly=1}
    private String symbol;
    private DateTime asof;
    private double totalRevenue=double.NaN;
    private double costOfRevenue=double.NaN;
    private double incomeTaxExpense=double.NaN;
    private double grossProfit = double.NaN;
    private double netIncome = double.NaN;
    private double sga = double.NaN;
    private double netIncomeApplicableToCommonShares = double.NaN;
    private double ebit = double.NaN;
    private double operatingExpenses = double.NaN;
    private double researchAndDevelopment = double.NaN;
    private double interestExpense = double.NaN;
    private PeriodType period;
    private DateTime modified;

    public IncomeStatement()
    {
    }
// It is appropriate to use the AsOf date in the comparison of the financial statements because the AsOf date is the statement date.
    public void MergeFrom(IncomeStatement previousIncomeStatement)
    {
      if(null==previousIncomeStatement)return;
      if(!Symbol.Equals(previousIncomeStatement.Symbol))return;
      if(!AsOf.Date.Equals(previousIncomeStatement.AsOf.Date))return;
      if(!Period.Equals(previousIncomeStatement.Period))return;
      if(Utility.IsZeroOrNaN(TotalRevenue))TotalRevenue=previousIncomeStatement.TotalRevenue;
      if(Utility.IsZeroOrNaN(CostOfRevenue))CostOfRevenue=previousIncomeStatement.CostOfRevenue;
      if(Utility.IsZeroOrNaN(IncomeTaxExpense))IncomeTaxExpense=previousIncomeStatement.IncomeTaxExpense;
      if(Utility.IsZeroOrNaN(GrossProfit))GrossProfit=previousIncomeStatement.GrossProfit;
      if(Utility.IsZeroOrNaN(NetIncome))NetIncome=previousIncomeStatement.NetIncome;
      if(Utility.IsZeroOrNaN(SGA))SGA=previousIncomeStatement.SGA;
      if(Utility.IsZeroOrNaN(NetIncomeApplicableToCommonShares))NetIncomeApplicableToCommonShares=previousIncomeStatement.NetIncomeApplicableToCommonShares;
      if(Utility.IsZeroOrNaN(EBIT))EBIT=previousIncomeStatement.EBIT;
      if(Utility.IsZeroOrNaN(OperatingExpenses))OperatingExpenses=previousIncomeStatement.OperatingExpenses;
      if(Utility.IsZeroOrNaN(ResearchAndDevelopment))ResearchAndDevelopment=previousIncomeStatement.ResearchAndDevelopment;
      if(Utility.IsZeroOrNaN(InterestExpense))InterestExpense=previousIncomeStatement.InterestExpense;
    }
    public String Symbol
    {
      get { return symbol; }
      set { symbol = value; }
    }
    public DateTime AsOf
    {
      get { return asof; }
      set { asof = value; }
    }
    public double TotalRevenue
    {
      get { return totalRevenue; }
      set { totalRevenue = value; }
    }
    public double CostOfRevenue
    {
      get { return costOfRevenue; }
      set { costOfRevenue = value; }
    }
    public double GrossProfit
    {
      get { return grossProfit; }
      set { grossProfit = value; }
    }
    public double NetIncome
    {
      get { return netIncome; }
      set { netIncome = value; }
    }
// this number is expressed as a percentage so multiply result by 100 to get the percent.
// this number tells you how much of every sales dollar you get to use in the business.
    public double GrossMargin
    {
      get
      {
        if (double.IsNaN(GrossProfit) || double.IsNaN(TotalRevenue)) return double.NaN;
        return (GrossProfit / TotalRevenue);
      }
    }
    public double IncomeTaxExpense
    {
      get { return incomeTaxExpense; }
      set { incomeTaxExpense = value; }
    }
    public double SGA
    {
      get { return sga; }
      set { sga = value; }
    }
    public double NetIncomeApplicableToCommonShares
    {
      get { return netIncomeApplicableToCommonShares; }
      set { netIncomeApplicableToCommonShares = value; }
    }
    public double EBIT
    {
      get { return ebit; }
      set { ebit = value; }
    }
    public double OperatingExpenses
    {
      get { return operatingExpenses; }
      set { operatingExpenses = value; }
    }
    public double ResearchAndDevelopment
    {
      get { return researchAndDevelopment; }
      set { researchAndDevelopment = value; }
    }
    public double InterestExpense
    {
      get { return interestExpense; }
      set { interestExpense = value; }
    }
    public PeriodType Period
    {
      get { return period; }
      set { period = value; }
    }
    public String PeriodAsString
    {
      get { return PeriodType.Quarterly.Equals(period) ? "Quarterly" : "Annual"; }
    }
    public DateTime Modified
    {
      get { return modified; }
      set { modified = value; }
    }
    public static String Heading
    {
      get
      {
        StringBuilder sb = new StringBuilder();
        sb.Append("Symbol,AsOf,TotalRevenue,CostOfRevenue,IncomeTaxExpense,GrossProfit,NetIncome,SG&A,NetIncomeApplicableToCommonShares,EBIT,Period");
        return sb.ToString();
      }
    }
    public override string ToString()
    {
      StringBuilder sb = new StringBuilder();
      sb.Append(symbol).Append(",");
      sb.Append(Utility.DateTimeToStringMMSDDSYYYY(asof)).Append(",");
      sb.Append(String.Format("{0:C}", totalRevenue)).Append(",");
      sb.Append(String.Format("{0:C}", costOfRevenue)).Append(",");
      sb.Append(String.Format("{0:C}", incomeTaxExpense)).Append(",");
      sb.Append(String.Format("{0:C}", grossProfit)).Append(",");
      sb.Append(String.Format("{0:C}", netIncome)).Append(",");
      sb.Append(String.Format("{0:C}", sga)).Append(",");
      sb.Append(String.Format("{0:C}", netIncomeApplicableToCommonShares)).Append(",");
      sb.Append(String.Format("{0:C}", ebit)).Append(",");
      sb.Append(String.Format("{0:C}", interestExpense)).Append(",");
      sb.Append(PeriodAsString);
      return sb.ToString();
    }
  }
}

