using System;
using System.Windows.Input;
using System.ComponentModel;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Windows;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Research.DynamicDataDisplay.DataSources;
using Microsoft.Research.DynamicDataDisplay.PointMarkers;
using MarketData;
using MarketData.Utils;
using MarketData.DataAccess;
using MarketData.MarketDataModel;
using TradeBlotter.DataAccess;
using TradeBlotter.Command;
using TradeBlotter.Model;
using System.Runtime.CompilerServices;

namespace TradeBlotter.ViewModels
{
  public class DividendPaymentViewModel : WorkspaceViewModel
  {
    private List<String> accounts;
    private List<String> symbols;
    private String selectedAccounts;

    private String selectedSymbols;
    private ObservableCollection<String> selectedSymbolsOverride = new ObservableCollection<String>();
    private DividendPaymentModelCollection dividendPaymentModelCollection = null;
    private String saveDocument;
    private RelayCommand saveCommand;
    private RelayCommand refreshCommand;                                     
    private bool showLabels = true;
    private bool busyIndicator = false;
    private bool ignoreSelectedSymbols = true;
    private CompositeDataSource valuePointsCompositeDataSource;
    private CompositeDataSource valuesCompositeDataSource;

    public DividendPaymentViewModel(bool loadedFromParams=false)
    {
      base.DisplayName = "Dividend Payments";
      accounts = DividendPaymentDA.GetDividendPaymentAccounts();
      accounts.Insert(0, Constants.CONST_ALL);
      selectedAccounts = accounts.Find(x => x.Equals(Constants.CONST_ALL));
      symbols = DividendPaymentDA.GetDividendPaymentSymbols(selectedAccounts);
      symbols.Insert(0, Constants.CONST_ALL);
      selectedSymbols = symbols[0];
      PropertyChanged += OnViewModelPropertyChanged;
      if (!loadedFromParams)
      {
        base.OnPropertyChanged("SelectedAccounts");
        base.OnPropertyChanged("SelectedItemsOverride");
      }
    }
    public void CreateCompositeDataSources()
    {
      if (null == dividendPaymentModelCollection) return;
      valuePointsCompositeDataSource = dividendPaymentModelCollection.CollectionToCompositeDataSource(true);
      valuesCompositeDataSource = dividendPaymentModelCollection.ToCompositeDataSource(true);
    }
    public void InitializeDataSources()
    {
      dividendPaymentModelCollection = null;
      if (valuePointsCompositeDataSource != null) valuePointsCompositeDataSource.Clear();
      if (valuesCompositeDataSource != null) valuesCompositeDataSource.Clear();
      base.OnPropertyChanged("DividendPayments");
      base.OnPropertyChanged("Values");
      base.OnPropertyChanged("ValuePoints");
      base.OnPropertyChanged("Markers");
    }

    public override SaveParameters GetSaveParameters()
    {
      SaveParameters saveParams = new SaveParameters();
      saveParams.Add(new KeyValuePair<String, String>("Type", GetType().Namespace + "." + GetType().Name));
      saveParams.Add(new KeyValuePair<String, String>("SelectedSymbols", Utility.ListToString(Utility.ToList(selectedSymbols),'|')));
      saveParams.Add(new KeyValuePair<String, String>("SelectedAccounts", Utility.ListToString(Utility.ToList(selectedAccounts),'|')));
      saveParams.Add(new KeyValuePair<String, String>("Symbols", Utility.ListToString(symbols,'|')));
      saveParams.Add(new KeyValuePair<String, String>("Accounts", Utility.ListToString(accounts, '|')));
      return saveParams;
    }
    public override void SetSaveParameters(SaveParameters saveParameters)
    {
      try
      {
        Referer = saveParameters.Referer;
        if(saveParameters.ContainsKey("SelectedSymbols")) selectedSymbols=Utility.ListToString(Utility.ToList((from KeyValuePair<String,String> item in saveParameters where item.Key.Equals("SelectedSymbols") select item).FirstOrDefault().Value,'|'),',');
        if(saveParameters.ContainsKey("SelectedAccounts")) selectedAccounts=Utility.ListToString(Utility.ToList((from KeyValuePair<String,String> item in saveParameters where item.Key.Equals("SelectedAccounts") select item).FirstOrDefault().Value,'|'),',');
        if(saveParameters.ContainsKey("Symbols")) symbols=Utility.ToList((from KeyValuePair<String,String> item in saveParameters where item.Key.Equals("Symbols") select item).FirstOrDefault().Value,'|');
        if(saveParameters.ContainsKey("Accounts")) accounts=Utility.ToList((from KeyValuePair<String,String> item in saveParameters where item.Key.Equals("Accounts") select item).FirstOrDefault().Value,'|');
        ignoreSelectedSymbols = false;
        base.OnPropertyChanged("SelectedSymbols");
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString()));
      }
    }
    public override bool CanPersist()
    {
      return true;
    }
    public ObservableCollection<DividendPaymentModel> DividendPayments
    {
      get
      {
        return dividendPaymentModelCollection;
      }
    }
    public bool BusyIndicator
    {
      get { return busyIndicator; }
      set
      {
        busyIndicator = value;
        base.OnPropertyChanged("BusyIndicator");
      }
    }
    private void OnViewModelPropertyChanged(object sender, PropertyChangedEventArgs eventArgs)
    {
      if (eventArgs.PropertyName.Equals("SelectedSymbols") && ignoreSelectedSymbols)
      {
        ignoreSelectedSymbols = false;
        return;
      }
      else if (eventArgs.PropertyName.Equals("SelectedSymbols"))
      {
        BusyIndicator = true;
        Task workerTask = Task.Factory.StartNew(() =>
        {
          InitializeDataSources();
          CheckSelectedItems();
          String accounts = null;
          if (selectedAccounts.Equals(Constants.CONST_ALL)) accounts = Utility.ListToString(DividendPaymentDA.GetDividendPaymentAccounts());
          else accounts = selectedAccounts;
          if (!"".Equals(selectedSymbols))
          {
            List<String> selectedAccountsInternal = GetSelectedItemsInternal(accounts);
            List<String> selectedSymbolsInternal = GetSelectedItemsInternal(selectedSymbols);
            DividendPayments dividendPayments = DividendPaymentDA.GetDividendPaymentsForAccountsAndSymbols(selectedAccountsInternal, selectedSymbolsInternal);
            dividendPaymentModelCollection = new DividendPaymentModelCollection(dividendPayments);
            CreateCompositeDataSources();
          }
        });
        workerTask.ContinueWith((continuation) =>
        {
          BusyIndicator = false;
          base.OnPropertyChanged("DividendPayments");
          base.OnPropertyChanged("Values");
          base.OnPropertyChanged("ValuePoints");
          base.OnPropertyChanged("Markers");
        });
      }
      else if (eventArgs.PropertyName.Equals("SelectedAccounts"))
      {
        BusyIndicator = true;
        Task workerTask = Task.Factory.StartNew(() =>
        {
          InitializeDataSources();
          ignoreSelectedSymbols = true;
          if (selectedAccounts.Equals(Constants.CONST_ALL)) symbols = DividendPaymentDA.GetDividendPaymentSymbols();
          else symbols = DividendPaymentDA.GetDividendPaymentSymbols(GetSelectedItemsInternal(selectedAccounts));
          if (symbols.Count > 1) symbols.Insert(0, Constants.CONST_ALL);
          Symbols = symbols;
          if (symbols.Count > 0)
          {
            SelectedSymbols = symbols[0];
            //            SetSelectedItems(symbols[0]);
            List<String> selectedAccountsInternal = GetSelectedItemsInternal(selectedAccounts);
            List<String> selectedSymbolsInternal = GetSelectedItemsInternal(selectedSymbols);
            DividendPayments dividendPayments = DividendPaymentDA.GetDividendPaymentsForAccountsAndSymbols(selectedAccountsInternal, selectedSymbolsInternal);
            dividendPaymentModelCollection = new DividendPaymentModelCollection(dividendPayments);
            CreateCompositeDataSources();
          }
          else dividendPaymentModelCollection = null;
        });
        workerTask.ContinueWith((continuation) =>
        {
          BusyIndicator = false;
          ignoreSelectedSymbols = false;
          base.OnPropertyChanged("DividendPayments");
          base.OnPropertyChanged("Values");
          base.OnPropertyChanged("ValuePoints");
          base.OnPropertyChanged("Markers");
        });
      }
    }
    public override String Title
    {
      get
      {
        return "Dividend Payments";
      }
    }
    public List<String> Accounts
    {
      get
      {
        return accounts;
      }
      set { ;}
    }
// Note : if more than one item is selected in the Symbols list we remove {All} from the selection list.  However, WPFToolkit CheckBoxCombo does not update the check mark on the {All} item
// so it remains visibly checked even though it is not checked.
    public String SelectedAccounts
    {
      get 
      { 
        return selectedAccounts ; 
      }
      set 
      { 
        List<String> selectedAccountsList = Utility.ToList(value);
        if (selectedAccountsList.Count > 1) selectedAccountsList.Remove(Constants.CONST_ALL);
        selectedAccounts = Utility.ListToString(selectedAccountsList);
        base.OnPropertyChanged("SelectedAccounts"); 
      }
    }
    private static List<String> GetSelectedItemsInternal(String selectedItemsStr)
    {
      List<String> selectedItems = Utility.ToList(selectedItemsStr);
      List<String> selectedItemsInternal = new List<String>();
      foreach (String selectedItem in selectedItems)
      {
        selectedItemsInternal.Add(selectedItem);
      }
      return selectedItemsInternal;
    }
    public List<String> Symbols
    {
      get
      {
        return symbols;
      }
      set
      {
        symbols = value;
        base.OnPropertyChanged("Symbols");
      }
    }
// Note : if more than one item is selected in the Symbols list we remove {All} from the selection list.  However, WPFToolkit CheckBoxCombo does not update the check mark on the {All} item
// so it remains visibly checked even though it is not checked.
    public String SelectedSymbols
    {
      get
      {
        return selectedSymbols;
      }
      set
      {
        if (null != value)
        {
          List<String> selectedSymbolsList = Utility.ToList(value);
          if (selectedSymbolsList.Count > 1) selectedSymbolsList.Remove(Constants.CONST_ALL);
          selectedSymbols = Utility.ListToString(selectedSymbolsList);
          base.OnPropertyChanged("SelectedSymbols");
        }
      }
    }
    private void CheckSelectedItems()
    {
      Application.Current.Dispatcher.Invoke((System.Windows.Forms.MethodInvoker)delegate()
      {
        if (null == selectedSymbolsOverride) return;
        if (selectedSymbolsOverride.Count > 1)
        {
          selectedSymbolsOverride.Remove(Constants.CONST_ALL);
        }
        else if (0 == selectedSymbolsOverride.Count)
        {  // select {All}
          selectedSymbolsOverride.Add(Constants.CONST_ALL);
        }
      });
    }
    public ObservableCollection<String> SelectedItemsOverride
    {
      get 
      { 
        return selectedSymbolsOverride;
      }
      set
      {
        selectedSymbolsOverride = value;
      }
    }


    public CompositeDataSource ValuePoints
    {
      get
      {
        if (null == dividendPaymentModelCollection) return null;
        
        return valuePointsCompositeDataSource;
      }
    }
    public CompositeDataSource Values
    {
      get
      {
        if (null == dividendPaymentModelCollection) return null;
        
        return valuesCompositeDataSource;
      }
    }
// This just adds a lot of noise to the screen
    public CenteredTextMarker[] Markers
    {
      get
      {
        return null;
        //if (!showLabels) return null;
        //if (null == dividendPaymentModelCollection) return null;
        //List<CenteredTextMarker> centeredTextMarkers = new List<CenteredTextMarker>();
        //for (int index = 0; index < dividendPaymentModelCollection.Count; index++)
        //{
        //  CenteredTextMarker centerTextMarker = new CenteredTextMarker();
        //  DividendPaymentModel dividendPaymentModel = dividendPaymentModelCollection[index];
        //  StringBuilder sb = new StringBuilder();
        //  sb.Append("(").Append(Utility.FormatCurrency(dividendPaymentModel.TotalAmount)).Append(")");
        //  centerTextMarker.Text = sb.ToString();
        //  centeredTextMarkers.Add(centerTextMarker);
        //}
        //return centeredTextMarkers.ToArray();
      }
    }
    private void Refresh()
    {
      accounts = DividendPaymentDA.GetDividendPaymentAccounts();
      accounts.Insert(0, Constants.CONST_ALL);
      selectedAccounts = accounts.Find(x => x.Equals(Constants.CONST_ALL));
      symbols = DividendPaymentDA.GetDividendPaymentSymbols(selectedAccounts);
      symbols.Insert(0, Constants.CONST_ALL);
      selectedSymbols = symbols[0];
      base.OnPropertyChanged("SelectedAccounts");
    }
    private bool CanRefresh
    {
      get { return true; }
    }
    public ICommand RefreshCommand
    {
      get
      {
        if (refreshCommand == null)
        {
          refreshCommand = new RelayCommand(param => this.Refresh(), param => this.CanRefresh);
        }
        return refreshCommand;
      }
    }
    public String SaveDocument
    {
      get { return saveDocument; }
      set { saveDocument = value; base.OnPropertyChanged("SaveDocument"); }
    }
    private void Save()
    {
      StringBuilder sb = new StringBuilder();
      sb.Append("DividendPayments_").Append(DateTime.Now.ToShortDateString()).Append(".xls");
      SaveDocument = sb.ToString();
    }
    private bool CanSave
    {
      get { return true; }
    }
    public ICommand SaveCommand
    {
      get
      {
        if (saveCommand == null)
        {
          saveCommand = new RelayCommand(param => this.Save(), param => this.CanSave);
        }
        return saveCommand;
      }
    }
  }
}