using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using Avalonia.Media;
using MarketData.Generator.Momentum;
using MarketData.MarketDataModel;
using MarketData.Utils;
using PortfolioManager.UIUtils;
using PortfolioManager.ViewModels;

namespace PortfolioManager.Models
{
  public class MGPositionModelCollection : ObservableCollection<MGPositionModel>
  {
    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 (MarketData.Generator.Momentum.Position position in slotPositions) Add(new MGPositionModel(position, keyIndex));
      }
    }
    public void Add(MarketData.Generator.Momentum.Positions allPositions)
    {
      foreach (MarketData.Generator.Momentum.Position position in allPositions) Add(new MGPositionModel(position));
    }
    public void OnCollectionChanged()
    {
      base.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset,null));
    }
  }
  public class MGPositionModel : ModelBase
  {
    private MarketData.Generator.Momentum.Position position = new MarketData.Generator.Momentum.Position();
    private int slot;
    private int priceChangeDirection=0;
    private double prevPrice=double.NaN;
    private DateTime lastUpdated=DateTime.Now;
    private double rsi3=double.NaN;

    public MGPositionModel()
    {
    }
    public MGPositionModel(MarketData.Generator.Momentum.Position position, int slot)
    {
      Slot=slot;
      Symbol=position.Symbol;
      PurchaseDate=position.PurchaseDate;
      SellDate=position.SellDate;
      Shares=position.Shares;
      PurchasePrice=position.PurchasePrice;
      CurrentPrice=position.CurrentPrice;
      Volume=position.Volume;
      Return1D=position.Return1D;
      CumReturn252=position.CumReturn252;
      IDIndicator=position.IDIndicator;
      Score=position.Score;
      MaxDrawdown=position.MaxDrawdown;
      MaxUpside=position.MaxUpside;
      Velocity=position.Velocity;
      PE=position.PE;
      Beta=position.Beta;
      ZacksRank=position.ZacksRank;
      SharpeRatio = position.SharpeRatio;
    }
    public MGPositionModel(MarketData.Generator.Momentum.Position position)
    {
      slot=-1;
      Symbol=position.Symbol;
      PurchaseDate=position.PurchaseDate;
      SellDate=position.SellDate;
      Shares=position.Shares;
      PurchasePrice=position.PurchasePrice;
      CurrentPrice=position.CurrentPrice;
      Volume=position.Volume;
      Return1D=position.Return1D;
      CumReturn252=position.CumReturn252;
      IDIndicator=position.IDIndicator;
      Score=position.Score;
      MaxDrawdown=position.MaxDrawdown;
      MaxUpside=position.MaxUpside;
      Velocity=position.Velocity;
      PE=position.PE;
      Beta=position.Beta;
      ZacksRank=position.ZacksRank;
      SharpeRatio = position.SharpeRatio;
    }

    public MarketData.Generator.Momentum.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 IBrush 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 IBrush SellDateColor
    {
      get
      {
        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 DateTime SellDate
    {
      get{return position.SellDate;}
      set{position.SellDate=value;base.OnPropertyChanged("SellDate");}
    }
    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 IBrush 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 IBrush 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 IBrush 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 IBrush 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 long Volume
    {
      get{return position.Volume;}
      set{position.Volume=value;base.OnPropertyChanged("Volume");}
    }
    public double Return1D
    {
      get{return position.Return1D;}
      set{position.Return1D=value;base.OnPropertyChanged("Return1D");}
    }
    public double GainLoss
    {
      get{return MarketValue-Exposure;}
    }
    public IBrush 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 IBrush 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 CumReturn252
    {
      get{return position.CumReturn252;}
      set{position.CumReturn252=value;base.OnPropertyChanged("CumReturn252");}
    }
    public double IDIndicator
    {
      get{return position.IDIndicator;}
      set{position.IDIndicator=value;base.OnPropertyChanged("IDIndicator");}
    }
    public double Score
    {
      get { return position.Score; }
      set { position.Score=value; base.OnPropertyChanged("Score"); }
    }
    public double MaxDrawdown
    {
      get{return position.MaxDrawdown;}
      set{position.MaxDrawdown=value;base.OnPropertyChanged("MaxDrawdown");}
    }
    public double MaxUpside
    {
      get{return position.MaxUpside;}
      set{position.MaxUpside=value;base.OnPropertyChanged("MaxUpside");}
    }
    public double Velocity
    {
      get{return position.Velocity;}
      set{position.Velocity=value;base.OnPropertyChanged("Velocity");}
    }
    public double PE
    {
      get{return position.PE;}
      set{position.PE=value;base.OnPropertyChanged("PE");}
    }
    public String ZacksRank
    {
      get {return position.ZacksRank;}
      set{position.ZacksRank=value;base.OnPropertyChanged("ZacksRank");}
    }
    public double Beta
    {
      get{return position.Beta;}
      set{position.Beta=value;base.OnPropertyChanged("Beta");}
    }
    public double SharpeRatio
    {
      get { return position.SharpeRatio; }
      set { position.SharpeRatio = value; base.OnPropertyChanged("SharpeRatio"); }
    }
    public bool IsActivePosition
    {
      get{return Utility.IsEpoch(SellDate)?true:false;}
    }
  }
}
