using MarketData.Generator;
using MarketData.MarketDataModel;
using MarketData.Utils;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
using TradeBlotter.ViewModels;
using TradeBlotter.UIUtils;
using System.Collections.Specialized;
using MarketData.Generator.CMTrend;
using MarketData;

using Position=MarketData.Generator.CMTrend.Position;
using StopLimit=MarketData.MarketDataModel.StopLimit;

using MarketData.DataAccess;
using TradeBlotter.Interface;

namespace TradeBlotter.Model
{
  public class CMTPositionModelCollection:ObservableCollection<CMTPositionModel>
  {
    public void Add(ActivePositions activePositions)
    {
      foreach(Position position in activePositions)Add(new CMTPositionModel(position));
    }
    public void Add(Positions allPositions)
    {
      foreach(Position position in allPositions) Add(new CMTPositionModel(position));
    }
    public void OnCollectionChanged()
    {
      base.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset,null));
    }
  }

  public class CMTPositionModel : ModelBase, IPositionModel
  {
    private Position position=new Position();
    private int priceChangeDirection=0;
    private double prevPrice=double.NaN;
    private double currentPriceLow=double.NaN;
    private DateTime lastUpdated=DateTime.Now;
    private double edgeRatio=double.NaN;

    public CMTPositionModel()
    {
    }
    public CMTPositionModel(Position position)
    {
      Symbol=position.Symbol;
      PurchaseDate=position.PurchaseDate;
      SellDate=position.SellDate;
      Shares=position.Shares;
      PurchasePrice=position.PurchasePrice;
      CurrentPrice=position.CurrentPrice;
      PositionRiskPercentDecimal=position.PositionRiskPercentDecimal;
      InitialStopLimit=position.InitialStopLimit;
      TrailingStopLimit=position.TrailingStopLimit;
      LastStopAdjustment=position.LastStopAdjustment;
      this.position.R=position.R;
      this.position.C=position.C;
    }
    public void UpdateProperties()
    {
      base.OnPropertyChanged("CurrentPrice");
      base.OnPropertyChanged("MarketValue");
      base.OnPropertyChanged("ActiveMarketValue");
      base.OnPropertyChanged("GainLoss");
      base.OnPropertyChanged("GainLossPcnt");
      base.OnPropertyChanged("RMultiple");
      base.OnPropertyChanged("EdgeRatioAsString");

      base.OnPropertyChanged("CurrentPriceColor");
      base.OnPropertyChanged("TrailingStopLimitColor");
      base.OnPropertyChanged("InitialStopLimitColor");
      base.OnPropertyChanged("TotalRiskExposureColor");
      base.OnPropertyChanged("ActiveMarketValueColor");
      base.OnPropertyChanged("GainLossColor");
      base.OnPropertyChanged("GainLossPcntColor");
      base.OnPropertyChanged("EdgeRatioAsStringColor");
      base.OnPropertyChanged("RMultipleColor");
    }
    public Position Position
    {
      get{return position;}
      set
      {
        Symbol=position.Symbol;
        PurchaseDate=position.PurchaseDate;
        SellDate=position.SellDate;
        Shares=position.Shares;
        PurchasePrice=position.PurchasePrice;
        CurrentPrice=position.CurrentPrice;
        PositionRiskPercentDecimal=position.PositionRiskPercentDecimal;
        InitialStopLimit=position.InitialStopLimit;
        TrailingStopLimit=position.TrailingStopLimit;
        LastStopAdjustment=position.LastStopAdjustment;
        this.position.R=position.R;
        this.position.C=position.C;
      }
    }
    public String Symbol
    {
      get { return position.Symbol; }
      set { position.Symbol=value; base.OnPropertyChanged("Symbol"); }
    }
    public Brush SymbolColor
    {
      get
      {
        if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue);
        return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
      }
    }
// ***
    public DateTime PurchaseDate
    {
      get { return position.PurchaseDate; }
      set { position.PurchaseDate=value; base.OnPropertyChanged("PurchaseDate"); }
    }

    public Brush PurchaseDateColor
    {
      get
      {
        DateGenerator dateGenerator=new DateGenerator();
        if(!dateGenerator.IsMarketOpen(PurchaseDate)) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red);
        if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue);
        return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
      }
    }

    public DateTime SellDate
    {
      get { return position.SellDate; }
      set { position.SellDate=value; base.OnPropertyChanged("SellDate"); }
    }

    public Brush SellDateColor
    {
      get
      {
        if(Utility.IsEpoch(SellDate)) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
        DateGenerator dateGenerator=new DateGenerator();
        if(!dateGenerator.IsMarketOpen(SellDate)) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red);
        if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue);
        return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
      }
    }
// ***
    public int DaysHeld
    {
      get
      {
        DateGenerator dateGenerator=new DateGenerator();
        if(Utility.IsEpoch(SellDate)) return dateGenerator.DaysBetween(PurchaseDate,DateTime.Now.Date);
        return dateGenerator.DaysBetween(PurchaseDate,SellDate);
      }
    }
    public Brush DaysHeldColor
    {
      get
      {
        if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue);
        return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
      }
    }
// ***
// Here we take R as based upon our StopLimit.  
    public double R
    {
      get
      {
        if(position.TrailingStopLimit>position.PurchasePrice)return 0.00;         // here we are considering the current risk/share which is based on our stop limit
        return position.TrailingStopLimit>position.PurchasePrice?0.00:position.PurchasePrice-position.TrailingStopLimit;
      }
    }
    public Brush RColor
    {
      get
      {
        if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue);
        return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
      }
    }
// ***
    public double TotalRiskExposure
    {
      get{return R*position.Shares;}
    }
    public Brush TotalRiskExposureColor
    {
      get
      {
        if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue);
        return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
      }
    }
// ***
    public double EdgeRatio
    {
      get{return edgeRatio;}
      set
      {
        edgeRatio=value;
        base.OnPropertyChanged("EdgeRatio");
        base.OnPropertyChanged("EdgeRatioAsStringColor");
      }
    }
    public String EdgeRatioAsString
    {
      get{return Utility.FormatNumber(edgeRatio,2,false);}    
    }
    public Brush EdgeRatioAsStringColor
    {
      get
      {
        if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue);
        if(double.IsNaN(edgeRatio))return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black); 
        if(edgeRatio>=1.00)return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Green);
        return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red);
      }
    }
// ***

    public String RMultipleAsString
    {
      get{return Utility.FormatNumber((position.CurrentPrice-position.PurchasePrice)/(position.PurchasePrice-position.InitialStopLimit),2,false)+"R";}    // always based on original position risk
    }

    public double RMultiple
    {
      get{return (position.CurrentPrice-position.PurchasePrice)/(position.PurchasePrice-position.InitialStopLimit);}    // always based on original position risk
    }

    public Brush RMultipleColor
    {
      get
      {
        if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue);
        return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
      }
    }
// ***
    public double PositionRiskPercentDecimal
    {
      get{return position.PositionRiskPercentDecimal;}
      set { position.PositionRiskPercentDecimal=value; base.OnPropertyChanged("PositionRiskPercentDecimal"); }
    }
    public double InitialStopLimit
    {
      get { return position.InitialStopLimit; }
      set 
      { 
        position.InitialStopLimit=value;
        base.OnPropertyChanged("InitialStopLimit");
        base.OnPropertyChanged("InitialStopLimitColor");
      }
    }
    public Brush InitialStopLimitColor
    {
      get
      {
        if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue);
        if(!Utility.IsEpoch(position.LastStopAdjustment)) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);  // if we have a trailing stop then we are no longer using the initial stop
        StopLimit stopLimit=PortfolioDA.GetStopLimit(position.Symbol);
        if(null==stopLimit||!stopLimit.StopPrice.Equals(Math.Round(position.InitialStopLimit,2))) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Purple);
        if(currentPriceLow<=position.InitialStopLimit) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red);
        return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
      }
    }
    public double TrailingStopLimit
    {
      get { return position.TrailingStopLimit; }
      set 
      { 
        position.TrailingStopLimit=value; 
        base.OnPropertyChanged("TrailingStopLimit"); 
        base.OnPropertyChanged("TrailingStopLimitColor");
      }
    }
    public Brush TrailingStopLimitColor
    {
      get
      {
        if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue);
        StopLimit stopLimit=PortfolioDA.GetStopLimit(position.Symbol);
        if(null==stopLimit||!stopLimit.StopPrice.Equals(Math.Round(position.TrailingStopLimit,2))) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Purple);
        if(currentPriceLow<=position.TrailingStopLimit)return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red);
        return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
      }
    }
// ***
    public DateTime LastStopAdjustment
    {
      get { return position.LastStopAdjustment; }
      set { position.LastStopAdjustment=value; base.OnPropertyChanged("LastStopAdjustment"); }
    }
    public Brush LastStopAdjustmentColor
    {
      get
      {
        if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue);
        return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
      }
    }
// ***
    public int DaysSinceLastStopAdjustment
    {
      get 
      {
        if(!IsActivePosition)return int.MinValue;
        DateGenerator dateGenerator=new DateGenerator();
        DateTime today=DateTime.Now;
        int daysSinceLastStopAdjustment=int.MinValue;
        if(Utility.IsEpoch(position.LastStopAdjustment)) daysSinceLastStopAdjustment=dateGenerator.DaysBetweenActual(today,position.PurchaseDate);
        else daysSinceLastStopAdjustment=dateGenerator.DaysBetweenActual(today,position.LastStopAdjustment);
        return daysSinceLastStopAdjustment; 
      }
    }
    public Brush DaysSinceLastStopAdjustmentColor
    {
      get
      {
        if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue);
        int daysSinceLastStopAdjustment=DaysSinceLastStopAdjustment;
        if(int.MinValue.Equals(daysSinceLastStopAdjustment))return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue);
        if(daysSinceLastStopAdjustment>=90) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red);
        else if(daysSinceLastStopAdjustment>=60) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red);               // I made them both red because yellow and purple looked horrible
        return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Green);
      }
    }

// ***
    public double Shares
    {
      get { return position.Shares; }
      set { position.Shares=value; base.OnPropertyChanged("Shares"); base.OnPropertyChanged("Exposure"); base.OnPropertyChanged("ActiveExposure"); base.OnPropertyChanged("MarketValue"); base.OnPropertyChanged("ActiveMarketValue"); base.OnPropertyChanged("GainLoss"); base.OnPropertyChanged("GainLossPcnt"); }
    }
    public Brush SharesColor
    {
      get
      {
        if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue);
        return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
      }
    }
// ***
    public double PurchasePrice
    {
      get { return position.PurchasePrice; }
      set { position.PurchasePrice=value; base.OnPropertyChanged("PurchasePrice"); base.OnPropertyChanged("Exposure"); base.OnPropertyChanged("ActiveExposure"); base.OnPropertyChanged("GainLoss"); base.OnPropertyChanged("GainLossPcnt"); }
    }
    public Brush PurchasePriceColor
    {
      get
      {
        if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue);
        return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
      }
    }
// ***
    public double CurrentPrice
    {
      get { return position.CurrentPrice; }
      set
      {
        if(position.CurrentPrice==value) return;
        position.CurrentPrice=value;
        if(double.IsNaN(prevPrice)) { prevPrice=position.CurrentPrice; priceChangeDirection=0; }
        else if(prevPrice>position.CurrentPrice) priceChangeDirection=-1;
        else if(prevPrice==position.CurrentPrice) priceChangeDirection=0;
        else priceChangeDirection=1;
        prevPrice=position.CurrentPrice;
        UpdateProperties();
      }
    }
    public Brush CurrentPriceColor
    {
      get
      {
        if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue);
        if(priceChangeDirection>0) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Green);
        else if(priceChangeDirection<0) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red);
        else return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
      }
    }
// ***

    public double CurrentPriceLow
    {
      get{return currentPriceLow;}
      set
      {
        if(currentPriceLow==value)return;
        currentPriceLow=value;
        base.OnPropertyChanged("CurrentPriceLow");
        base.OnPropertyChanged("CurrentPriceLowAsString");
        base.OnPropertyChanged("TrailingStopLimitColor");
        base.OnPropertyChanged("InitialStopLimitColor");
      }
    }
// ***
    public String CurrentPriceLowAsString
    {
      get { return Utility.FormatCurrency(currentPriceLow); }
    }
    public Brush CurrentPriceLowAsStringColor
    {
      get
      {
        if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue);
        return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
      }
    }
// ***
    public DateTime LastUpdated
    {
      get { return lastUpdated; }
      set { lastUpdated=value; base.OnPropertyChanged("LastUpdated"); }
    }
    public Brush LastUpdatedColor
    {
      get
      {
        if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue);
        return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
      }
    }
 // ***

    public double Exposure
    {
      get { return Shares*PurchasePrice; }
    }
    public double ActiveExposure
    {
      get { return IsActivePosition?Exposure:0.00; }
    }
    public Brush ActiveExposureColor
    {
      get
      {
        if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue);
        else return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
      }
    }
    public double MarketValue
    {
      get { return Shares*CurrentPrice; }
    }
    public double ActiveMarketValue
    {
      get { return IsActivePosition?MarketValue:0.00; }
    }
    public Brush ActiveMarketValueColor
    {
      get
      {
        if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue);
        if(ActiveMarketValue>Exposure) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Green);
        else if(ActiveMarketValue<Exposure) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red);
        else return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
      }
    }
    public double GainLoss
    {
      get { return MarketValue-Exposure; }
    }
    public Brush GainLossColor
    {
      get
      {
        if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue);
        if(GainLoss>0) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Green);
        else if(GainLoss<0) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red);
        else return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
      }
    }
    public double GainLossPcnt
    {
      get { return (MarketValue-Exposure)/Exposure; }
    }
    public Brush GainLossPcntColor
    {
      get
      {
        if(!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue);
        if(GainLoss>0) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Green);
        else if(GainLoss<0) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red);
        else return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Black);
      }
    }
    public bool IsActivePosition
    {
      get { return Utility.IsEpoch(SellDate)?true:false; }
    }
  }
}

