using System;
using System.Linq;
using System.Collections.Generic;
using MarketData;
using MarketData.MarketDataModel;
using MarketData.MarketDataModel.GainLoss;
using MarketData.Utils;
using MarketData.DataAccess;
using MarketData.Cache;

namespace MarketData.Generator.GainLoss
{
  public class GainLossHelper
  {
    private GainLossHelper()
    {
    }
    public static double? GetTotalGainLoss(DateTime holdingDate,PortfolioTrade portfolioTrade)
    {
      if(holdingDate<portfolioTrade.TradeDate) return null;
      if(portfolioTrade.IsOpen||(portfolioTrade.IsClosed&&portfolioTrade.SellDate>holdingDate))
      {
        Price price=LocalPriceCache.GetInstance().GetPrice(portfolioTrade.Symbol,holdingDate);
        if(null==price)
        {
          MDTrace.WriteLine(LogLevel.DEBUG,String.Format("No price for {0} on {1}",portfolioTrade.Symbol,Utility.DateTimeToStringMMHDDHYYYY(holdingDate)));
          return null;
        }
        return (price.Close*portfolioTrade.Shares)-(portfolioTrade.Shares*portfolioTrade.Price);
      }
      return (portfolioTrade.SellPrice*portfolioTrade.Shares)-(portfolioTrade.Price*portfolioTrade.Shares);
    }
    public static double? GetTotalMarketValue(DateTime holdingDate,PortfolioTrade portfolioTrade)
    {
      if(holdingDate<portfolioTrade.TradeDate) return null;
      if(portfolioTrade.IsOpen||(portfolioTrade.IsClosed&&portfolioTrade.SellDate>holdingDate))
      {
        Price price=LocalPriceCache.GetInstance().GetPrice(portfolioTrade.Symbol,holdingDate);
        if(null==price)
        {
          MDTrace.WriteLine(LogLevel.DEBUG,String.Format("No price for {0} on {1}",portfolioTrade.Symbol,Utility.DateTimeToStringMMHDDHYYYY(holdingDate)));
          return null;
        }
        return (price.Close*portfolioTrade.Shares);
      }
      return (portfolioTrade.SellPrice*portfolioTrade.Shares);
    }
    public static double? GetTotalExposure(DateTime holdingDate,PortfolioTrade portfolioTrade)
    {
      if(holdingDate<portfolioTrade.TradeDate) return null;
      return portfolioTrade.Shares*portfolioTrade.Price;
    }
    public static double? GetTotalCostBasis(DateTime holdingDate,PortfolioTrade portfolioTrade)
    {
      if(holdingDate<portfolioTrade.TradeDate) return null;
      return portfolioTrade.Price*portfolioTrade.Shares;
    }
    public static double? GetGainLoss(DateTime holdingDate,PortfolioTrade portfolioTrade)
    {
      if(holdingDate<portfolioTrade.TradeDate) return null;
      if(!portfolioTrade.SellDate.Equals(Utility.Epoch)&&holdingDate>portfolioTrade.SellDate) return null;
      // check to see if we sold this on holdingDate
      if(!portfolioTrade.SellDate.Equals(Utility.Epoch)&&holdingDate.Equals(portfolioTrade.SellDate))
      {
        return (portfolioTrade.SellPrice*portfolioTrade.Shares)-(portfolioTrade.Price*portfolioTrade.Shares);
      }
      // check to see if we bought and sold on the same date.
      if(portfolioTrade.SellDate.Equals(portfolioTrade.TradeDate))
      {
        return (portfolioTrade.SellPrice*portfolioTrade.Shares)-(portfolioTrade.Price*portfolioTrade.Shares);
      }
      Price price=LocalPriceCache.GetInstance().GetPrice(portfolioTrade.Symbol,holdingDate);
      if(null==price)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("No price for {0} on {1}",portfolioTrade.Symbol,Utility.DateTimeToStringMMHDDHYYYY(holdingDate)));
        return null;
      }
      return (price.Close*portfolioTrade.Shares)-(portfolioTrade.Shares*portfolioTrade.Price);
    }
    public static double? GetMarketValue(DateTime holdingDate,PortfolioTrade portfolioTrade)
    {
      if(holdingDate<portfolioTrade.TradeDate) return null;
      if(!portfolioTrade.SellDate.Equals(Utility.Epoch)&&holdingDate>portfolioTrade.SellDate) return null;
      // check to see if we bought and sold on the same date.
      if(portfolioTrade.SellDate.Equals(portfolioTrade.TradeDate)) return (portfolioTrade.SellPrice*portfolioTrade.Shares);
      Price price=LocalPriceCache.GetInstance().GetPrice(portfolioTrade.Symbol,holdingDate);
      if(null==price)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("No price for {0} on {1}",portfolioTrade.Symbol,Utility.DateTimeToStringMMHDDHYYYY(holdingDate)));
        return null;
      }
      return portfolioTrade.Shares*price.Close;
    }

    public static double? GetCostBasis(DateTime holdingDate,PortfolioTrade portfolioTrade)
    {
      if(holdingDate<portfolioTrade.TradeDate) return null;
      if(!portfolioTrade.SellDate.Equals(Utility.Epoch)&&holdingDate>portfolioTrade.SellDate) return null;
      return portfolioTrade.Price*portfolioTrade.Shares;
    }

    public static double? GetExposure(DateTime holdingDate,PortfolioTrade portfolioTrade)
    {
      if(holdingDate<portfolioTrade.TradeDate) return null;
      if(!portfolioTrade.SellDate.Equals(Utility.Epoch)&&holdingDate>portfolioTrade.SellDate) return null;
      return portfolioTrade.Shares*portfolioTrade.Price;
    }

  }
}

