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;
using MarketData.Generator.CMMomentum;
using Position=MarketData.Generator.CMMomentum.Position;

namespace TradeBlotter.Model
{
  public class CMPositionModelCollection : ObservableCollection<CMPositionModel>
  {
    public void Add(ActivePositions activePositions)
    {
      List<int> slotKeys = new List<int>(activePositions.Keys);
      for (int keyIndex = 0; keyIndex < slotKeys.Count; keyIndex++)
      {
        Positions slotPositions = activePositions[slotKeys[keyIndex]];
        foreach (Position position in slotPositions) Add(new CMPositionModel(position, keyIndex));
      }
    }
    public void Add(Positions allPositions)
    {
      foreach (Position position in allPositions) Add(new CMPositionModel(position));
    }
    public void OnCollectionChanged()
    {
      base.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset, null));
    }
  }
// ************************************************************************************************************************************************************************************
  public class CMPositionModel : ModelBase
  {
    private Position position = new Position();
    private int slot;
    private int priceChangeDirection = 0;
    private double prevPrice = double.NaN;
    private DateTime lastUpdated = DateTime.Now;
    private double rsi3 = double.NaN;

    public CMPositionModel()
    {
    }

    public CMPositionModel(Position position, int slot)
    {
      Slot = slot;
      Symbol = position.Symbol;
      PurchaseDate = position.PurchaseDate;
      SellDate = position.SellDate;
      Shares = position.Shares;
      PurchasePrice = position.PurchasePrice;
      CurrentPrice = position.CurrentPrice;
      Beta = position.Beta;
      BetaMonths = position.BetaMonths;
      SharpeRatio = position.SharpeRatio;
      CNNPrediction = position.CNNPrediction;
    }

    public CMPositionModel(Position position)
    {
      slot = -1;
      Symbol = position.Symbol;
      PurchaseDate = position.PurchaseDate;
      SellDate = position.SellDate;
      Shares = position.Shares;
      PurchasePrice = position.PurchasePrice;
      CurrentPrice = position.CurrentPrice;
      Beta = position.Beta;
      BetaMonths = position.BetaMonths;
      SharpeRatio = position.SharpeRatio;
      CNNPrediction = position.CNNPrediction;
    }

    public Position Position
    {
      get
      {
        return position;
      }
    }

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

    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 int Slot
    {
      get { return slot; }
      set { slot = value; base.OnPropertyChanged("Slot"); }
    }

    public String SlotAsString
    {
      get
      {
        if (-1 == Slot) return Constants.CONST_DASHES;
        return Slot.ToString();
      }
    }

    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 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 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;
        base.OnPropertyChanged("CurrentPrice");
        base.OnPropertyChanged("MarketValue");
        base.OnPropertyChanged("ActiveMarketValue");
        base.OnPropertyChanged("GainLoss");
        base.OnPropertyChanged("GainLossPcnt");
        base.OnPropertyChanged("CurrentPriceColor");
      }
    }

    public double RSI3
    {
      get { return rsi3; }
      set
      {
        if (rsi3 == value) return;
        rsi3 = value;
        base.OnPropertyChanged("RSI3");
        base.OnPropertyChanged("RSI3Color");
      }
    }

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

    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 Brush RSI3Color
    {
      get
      {
        if (!IsActivePosition) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Blue);
        if (RSI3 < 10 || RSI3 > 80) return BrushCollection.GetContextBrush(BrushCollection.BrushColor.Red);
        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 bool CNNPrediction
    {
      get { return position.CNNPrediction; }
      set { position.CNNPrediction = value; base.OnPropertyChanged("CNNPrediction"); }
    }

    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 double Beta
    {
      get { return position.Beta; }
      set { position.Beta = value; base.OnPropertyChanged("Beta"); }
    }

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

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

    public bool IsActivePosition
    {
      get { return Utility.IsEpoch(SellDate) ? true : false; }
    }
  }
}
