using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
using MarketData.Utils;
using MarketData.MarketDataModel;
using MarketData.DataAccess;
using MarketData.ValueAtRisk;
using TradeBlotter.Command;
using TradeBlotter.Model;
using System.Windows;

namespace TradeBlotter.ViewModels
{
  public class ValueAtRiskViewModel : WorkspaceViewModel
  {
    private List<String> dayCounts = new List<String>() { "30", "60", "90", "180", "252","504" };
    private List<String> confidenceValues = new List<String>() {"90","95","98" };
    private String selectedDayCount;
    private String selectedConfidence;
    private DateTime selectedDate = Utility.Epoch;
    private DateTime selectableDateStart = Utility.Epoch;
    private DateTime selectableDateEnd = DateTime.Now;
    private PortfolioHoldingViewModel selectedItem = null;
    private ObservableCollection<PortfolioHoldingViewModel> portfolioHoldingsViewModelCollection = null;
    private VaRResult varResult;
    private bool busyIndicator = true;
    private String busyContent = "Calculating VaR";
    private RelayCommand removeCommand;
    private RelayCommand resetCommand;

    public ValueAtRiskViewModel()
    {
      base.DisplayName = "ValueAtRiskViewModel";
      PropertyChanged += OnValueAtRiskViewModelPropertyChanged;
      Initialize();
    }
    private void Initialize()
    {
      BusyIndicator = true;
      selectedDayCount = dayCounts[3];
      selectedConfidence = confidenceValues[1];
      PortfolioTrades portfolioTrades = PortfolioDA.GetOpenTrades();
      selectableDateStart=(from portfolioTrade in portfolioTrades select portfolioTrade.TradeDate).Min();
      List<String> holdingSymbols = (from portfolioTrade in portfolioTrades select portfolioTrade.Symbol).Distinct().ToList();
      selectedDate = selectableDateEnd=PricingDA.GetLatestDate(holdingSymbols);
      PortfolioHoldings portfolioHoldings = PortfolioHoldings.GetPortfolioHoldings(portfolioTrades, Int16.Parse(selectedDayCount),selectedDate);
      portfolioHoldingsViewModelCollection =PortfolioHoldingsViewModelCollectionHelper.CreateCollection(portfolioHoldings);
      varResult = HistoricalVaR.GetVaR(portfolioHoldings, double.Parse(selectedConfidence));
      base.OnPropertyChanged("SelectedDayCount");
      base.OnPropertyChanged("SelectedConfidence");
      base.OnPropertyChanged("AllHoldings");
      base.OnPropertyChanged("ValueAtRisk");
      base.OnPropertyChanged("ValueAtRiskPercent");
      base.OnPropertyChanged("SelectedDate");
      BusyIndicator = false;
    }
    private void CalculateVaR()
    {
    }
    public override SaveParameters GetSaveParameters()
    {
      return null;
    }
    public override void SetSaveParameters(SaveParameters saveParameters)
    {
    }
    public override bool CanPersist()
    {
      return false;
    }
    private void OnValueAtRiskViewModelPropertyChanged(object sender, PropertyChangedEventArgs eventArgs)
    {
      if (eventArgs.PropertyName.Equals("SelectedDate"))
      {
        Task workerTask = Task.Factory.StartNew(() =>
        {
          BusyIndicator = true;
          PortfolioTrades portfolioTrades = PortfolioDA.GetOpenTradesAsOf(selectedDate);
          PortfolioHoldings portfolioHoldings = PortfolioHoldings.GetPortfolioHoldings(portfolioTrades, Int16.Parse(selectedDayCount), selectedDate);
          varResult = HistoricalVaR.GetVaR(portfolioHoldings, double.Parse(selectedConfidence));
          portfolioHoldingsViewModelCollection = PortfolioHoldingsViewModelCollectionHelper.CreateCollection(portfolioHoldings);
          if(!varResult.Success) {MessageBox.Show(varResult.Message,varResult.Success.ToString());ZeroVaRData();}
        });
        workerTask.ContinueWith((continuation)=>
        {
          BusyIndicator = false;
          base.OnPropertyChanged("AllHoldings");
          base.OnPropertyChanged("ValueAtRisk");
          base.OnPropertyChanged("ValueAtRiskPercent");
        });
      }
      else if (eventArgs.PropertyName.Equals("SelectedDayCount"))
      {
        BusyIndicator = true;
        Task workerTask = Task.Factory.StartNew(() =>
        {
          PortfolioHoldings portfolioHoldings = PortfolioHoldingsViewModelCollectionHelper.CreateCollection(portfolioHoldingsViewModelCollection);
          portfolioHoldings.UpdateDayCount(Int16.Parse(selectedDayCount));
          varResult = HistoricalVaR.GetVaR(portfolioHoldings, double.Parse(selectedConfidence));
          portfolioHoldingsViewModelCollection = PortfolioHoldingsViewModelCollectionHelper.CreateCollection(portfolioHoldings);
          if(!varResult.Success) {MessageBox.Show(varResult.Message,varResult.Success.ToString());ZeroVaRData();}
        });
        workerTask.ContinueWith((continuation) =>
        {
          BusyIndicator = false;
          base.OnPropertyChanged("AllHoldings");
          base.OnPropertyChanged("ValueAtRisk");
          base.OnPropertyChanged("ValueAtRiskPercent");
        });
      }
      else if (eventArgs.PropertyName.Equals("SelectedConfidence"))
      {
        BusyIndicator = true;
        Task workerTask = Task.Factory.StartNew(() =>
        {
          PortfolioHoldings portfolioHoldings = PortfolioHoldingsViewModelCollectionHelper.CreateCollection(portfolioHoldingsViewModelCollection);
          varResult = HistoricalVaR.GetVaR(portfolioHoldings, double.Parse(selectedConfidence));
          portfolioHoldingsViewModelCollection = PortfolioHoldingsViewModelCollectionHelper.CreateCollection(portfolioHoldings);
          if(!varResult.Success) {MessageBox.Show(varResult.Message,varResult.Success.ToString());ZeroVaRData();}
        });
        workerTask.ContinueWith((continuation) =>
        {
          BusyIndicator = false;
          base.OnPropertyChanged("AllHoldings");
          base.OnPropertyChanged("ValueAtRisk");
          base.OnPropertyChanged("ValueAtRiskPercent");
        });
      }
    }
    public bool BusyIndicator
    {
      get{return busyIndicator;}
      set
      {
        busyIndicator=value;
        base.OnPropertyChanged("BusyIndicator");
      }
    }
    public String BusyContent
    {
      get{return busyContent;}
    }
    public override String Title
    {
      get { return "Historical VaR"; }
    }
    public PortfolioHoldingViewModel SelectedItem
    {
      get
      {
        return selectedItem;
      }
      set
      {
        selectedItem = value;
        foreach (PortfolioHoldingViewModel portfolioHoldingViewModel in portfolioHoldingsViewModelCollection)
        {
          portfolioHoldingViewModel.IsSelected = false;
        }
        if (null != selectedItem)
        {
          selectedItem.IsSelected = true;
        }
      }
    }
    private void ZeroVaRData()
    {
      foreach(PortfolioHoldingViewModel item in portfolioHoldingsViewModelCollection)
      {
        item.Contribution=0.00;
        item.ContributionDate=Utility.Epoch;
      }
    }
// VaR measure a negaitve event (i.e.) losses to portfolio value and is therefore a negative number.  However, convention has been to display this number as a positive number
// presumably to make for an easier visual interpretation.  We follow that convention here by making VaR positive as it is passed to the view.
    public double ValueAtRisk
    {
      get
      {
        return Math.Abs(varResult.VaRExpectedLoss);
      }
    }
    public double ValueAtRiskPercent
    {
      get
      {
        return Math.Abs(varResult.VaRPercent);
      }
    }
    public ObservableCollection<PortfolioHoldingViewModel> AllHoldings
    {
      get
      {
        return portfolioHoldingsViewModelCollection;
      }
      set
      {
        portfolioHoldingsViewModelCollection = value;
      }
    }
    public List<String> DayCounts
    {
      get { return dayCounts; }
    }
    public String SelectedDayCount
    {
      get
      {
        return selectedDayCount;
      }
      set
      {
        selectedDayCount = value;
        base.OnPropertyChanged("SelectedDayCount");
      }
    }
    public List<String> ConfidenceValues
    {
      get { return confidenceValues; }
    }
    public String SelectedConfidence
    {
      get
      {
        return selectedConfidence;
      }
      set
      {
        selectedConfidence = value;
        base.OnPropertyChanged("SelectedConfidence");
      }
    }
    public DateTime SelectedDate
    {
      get
      {
        return selectedDate;
      }
      set
      {
        if (!value.Date.Equals(selectedDate.Date))
        {
          selectedDate = value;
          base.OnPropertyChanged("SelectedDate");
        }
      }
    }
    public DateTime SelectableDateStart
    {
      get { return selectableDateStart; }
    }
    public DateTime SelectableDateEnd
    {
      get { return selectableDateEnd; }
    }
// ****************************************************C O M M A N D S ***************************************************
    private void Reset()
    {
      Initialize();
    }
    private bool CanReset
    {
      get { return true; }
    }
    public ICommand ResetCommand
    {
      get
      {
        if (resetCommand == null)
        {
          resetCommand = new RelayCommand(param => this.Reset(), param => this.CanReset);
        }
        return resetCommand;
      }
    }

    private void Remove()
    {
      if (null == selectedItem)
      {
        Console.Beep();
        return;
      }
      BusyIndicator = true;
      portfolioHoldingsViewModelCollection.Remove(selectedItem);
      PortfolioHoldings portfolioHoldings = PortfolioHoldingsViewModelCollectionHelper.CreateCollection(portfolioHoldingsViewModelCollection);
      varResult = HistoricalVaR.GetVaR(portfolioHoldings, double.Parse(selectedConfidence));
      portfolioHoldingsViewModelCollection=PortfolioHoldingsViewModelCollectionHelper.CreateCollection(portfolioHoldings);
      BusyIndicator = false;
      selectedItem = null;
      base.OnPropertyChanged("AllHoldings");
      base.OnPropertyChanged("ValueAtRisk");
      base.OnPropertyChanged("ValueAtRiskPercent");
      base.OnPropertyChanged("SelectedItem");
    }
    private bool CanRemove
    {
      get { return true; }
    }
    public ICommand RemoveCommand
    {
      get
      {
        if (removeCommand == null)
        {
          removeCommand = new RelayCommand(param => this.Remove(), param => this.CanRemove);
        }
        return removeCommand;
      }
    }
  }
}
