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

namespace TradeBlotter.ViewModels
{
  public class MACDViewModel : WorkspaceViewModel
  {
    private MACDFastSlowSignals macdFastSlowSignals;
    public enum SignalIndicator{SlowWeakSell=0,SlowWeakBuy,SlowStrongSell,SlowStrongBuy,FastWeakBuy,FastWeakSell,FastStrongBuy,FastStrongSell};
    Signals[] signals=new Signals[((int)SignalIndicator.FastStrongSell)+1];
    private String symbol;
    private String companyName;
    private List<String> symbols;
    private List<String> watchLists;
    private String selectedWatchList;
    private RelayCommand refreshCommand;
    private List<Int32> dayCounts;
    private Int32 selectedDayCount;
    private bool isLegendVisible = true;
    private bool busyIndicator = false;

    public MACDViewModel()
    {
      base.DisplayName = "MACDView";
      watchLists = WatchListDA.GetWatchLists();
      watchLists.Insert(0, Constants.CONST_ALL);
      selectedWatchList = watchLists.Find(x => x.Equals("Valuations"));
      symbols = WatchListDA.GetWatchList(selectedWatchList);
      dayCounts = new List<Int32>();
      dayCounts.Add(60);
      dayCounts.Add(90);
      dayCounts.Add(180);
      dayCounts.Add(360);
      dayCounts.Add(720);
      dayCounts.Add(1440);
      dayCounts.Add(3600);
      selectedDayCount = dayCounts[1];
      PropertyChanged += OnMACDViewModelPropertyChanged;
    }
    public override SaveParameters GetSaveParameters()
    {
      SaveParameters saveParams = new SaveParameters();
      if (null == symbol) return null;
      saveParams.Add(new KeyValuePair<String, String>("Type", GetType().Namespace + "." + GetType().Name));
      saveParams.Add(new KeyValuePair<String, String>("SelectedSymbol", symbol));
      saveParams.Add(new KeyValuePair<String, String>("SelectedWatchList", selectedWatchList));
      saveParams.Add(new KeyValuePair<String, String>("SelectedDayCount", selectedDayCount.ToString()));
      saveParams.Add(new KeyValuePair<String, String>("IsLegendVisible", isLegendVisible.ToString()));
      return saveParams;
    }
    public override void SetSaveParameters(SaveParameters saveParameters)
    {
      try
      {
        symbol = (from KeyValuePair<String, String> item in saveParameters where item.Key.Equals("SelectedSymbol") select item).FirstOrDefault().Value;
        selectedWatchList = (from KeyValuePair<String, String> item in saveParameters where item.Key.Equals("SelectedWatchList") select item).FirstOrDefault().Value;
        base.OnPropertyChanged("SelectedWatchList");
        selectedDayCount = Int32.Parse((from KeyValuePair<String, String> item in saveParameters where item.Key.Equals("SelectedDayCount") select item).FirstOrDefault().Value);
        try { isLegendVisible = Boolean.Parse((from KeyValuePair<String, String> item in saveParameters where item.Key.Equals("IsLegendVisible") select item).FirstOrDefault().Value); }
        catch (Exception exception) 
        {
          MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString()));
        }
        Referer=saveParameters.Referer;
        base.OnPropertyChanged("SelectedSymbol");
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Exception:{0}",exception.ToString()));
      }
    }
    public override bool CanPersist()
    {
      return true;
    }
    public bool BusyIndicator
    {
      get { return busyIndicator; }
      set
      {
        busyIndicator = value;
        base.OnPropertyChanged("BusyIndicator");
      }
    }
    private void OnMACDViewModelPropertyChanged(object sender, PropertyChangedEventArgs eventArgs)
    {
      if (eventArgs.PropertyName.Equals("SelectedSymbol")||(eventArgs.PropertyName.Equals("SelectedDayCount")&&null!=symbol))
      {
        BusyIndicator = true;
        Task workerTask = Task.Factory.StartNew(() =>
        {
          base.DisplayName = "MACD (" + symbol + ")";
          base.OnPropertyChanged("DisplayName");
          base.OnPropertyChanged("Title");
          macdFastSlowSignals = MACDGenerator.GenerateMACD(symbol, selectedDayCount);

          signals[(int)SignalIndicator.SlowWeakSell]=macdFastSlowSignals.SlowCondensedSignals.WeakSellSignals;
          signals[(int)SignalIndicator.SlowWeakBuy]=macdFastSlowSignals.SlowCondensedSignals.WeakBuySignals;
          signals[(int)SignalIndicator.SlowStrongSell]=macdFastSlowSignals.SlowCondensedSignals.StrongSellSignals;
          signals[(int)SignalIndicator.SlowStrongBuy]=macdFastSlowSignals.SlowCondensedSignals.StrongBuySignals;
          signals[(int)SignalIndicator.FastWeakSell]=macdFastSlowSignals.FastCondensedSignals.WeakSellSignals;
          signals[(int)SignalIndicator.FastWeakBuy]=macdFastSlowSignals.FastCondensedSignals.WeakBuySignals;
          signals[(int)SignalIndicator.FastStrongSell]=macdFastSlowSignals.FastCondensedSignals.StrongSellSignals;
          signals[(int)SignalIndicator.FastStrongBuy]=macdFastSlowSignals.FastCondensedSignals.StrongBuySignals;

          companyName = PricingDA.GetNameForSymbol(symbol);
        });
        workerTask.ContinueWith((continuation) =>
        {
          BusyIndicator = false;
          base.OnPropertyChanged("SignalSlow");
          base.OnPropertyChanged("MACDSlow");
          base.OnPropertyChanged("SignalFast");
          base.OnPropertyChanged("MACDFast");

          base.OnPropertyChanged("MACDFastWeakBuy");   
          base.OnPropertyChanged("MACDFastStrongBuy");
          base.OnPropertyChanged("MACDFastWeakSell");
          base.OnPropertyChanged("MACDFastStrongSell");
          base.OnPropertyChanged("MACDSlowWeakBuy");   
          base.OnPropertyChanged("MACDSlowStrongBuy");
          base.OnPropertyChanged("MACDSlowWeakSell");
          base.OnPropertyChanged("MACDSlowStrongSell");

          base.OnPropertyChanged("TitleSlow");
          base.OnPropertyChanged("TitleFast");
          base.OnPropertyChanged("LegendVisible");
        });
      }
      else if (eventArgs.PropertyName.Equals("SelectedWatchList"))
      {
//        if (selectedWatchList.Equals(Constants.CONST_ALL)) symbols = PricingDA.GetSymbols();
        if (selectedWatchList.Equals(Constants.CONST_ALL)) symbols = SymbolCache.GetInstance().GetSymbols();
        else symbols = WatchListDA.GetWatchList(selectedWatchList);
        base.OnPropertyChanged("Symbols");
      }
    }
// ****************************************************** C O M P O S I T E   S O U R C E S  S I G N A L S  B U Y S / S E L L S****************************************************
// Slow buy/sell signal markers
    public CompositeDataSource MACDSlowWeakBuy
    {
      get
      {
        if(null==signals||0==signals.Length||null==macdFastSlowSignals)return null;
        CompositeDataSource compositeDataSource = MACDModel.Signals(signals[(int)SignalIndicator.SlowWeakBuy],macdFastSlowSignals.MinSlowMACD);
        return compositeDataSource;      
      }
    }
    public CompositeDataSource MACDSlowStrongBuy
    {
      get
      {
        if(null==signals||0==signals.Length||null==macdFastSlowSignals)return null;
        CompositeDataSource compositeDataSource = MACDModel.Signals(signals[(int)SignalIndicator.SlowStrongBuy],macdFastSlowSignals.MinSlowMACD);
        return compositeDataSource;    
      }
    }
    public CompositeDataSource MACDSlowWeakSell
    {
      get
      {
        if(null==signals||0==signals.Length||null==macdFastSlowSignals)return null;
        CompositeDataSource compositeDataSource = MACDModel.Signals(signals[(int)SignalIndicator.SlowWeakSell],macdFastSlowSignals.MinSlowMACD);
        return compositeDataSource;    
      }
    }
    public CompositeDataSource MACDSlowStrongSell
    {
      get
      {
        if(null==signals||0==signals.Length||null==macdFastSlowSignals)return null;
        CompositeDataSource compositeDataSource = MACDModel.Signals(signals[(int)SignalIndicator.SlowStrongSell],macdFastSlowSignals.MinSlowMACD);
        return compositeDataSource;
      }
    }
// Fast buy/sell signal markers

    public CompositeDataSource MACDFastWeakBuy
    {
      get
      {
        if(null==signals||0==signals.Length||null==macdFastSlowSignals)return null;
        CompositeDataSource compositeDataSource = MACDModel.Signals(signals[(int)SignalIndicator.FastWeakBuy],macdFastSlowSignals.MinFastMACD);
        return compositeDataSource;      
      }
    }
    public CompositeDataSource MACDFastStrongBuy
    {
      get
      {
        if(null==signals||0==signals.Length||null==macdFastSlowSignals)return null;
        CompositeDataSource compositeDataSource = MACDModel.Signals(signals[(int)SignalIndicator.FastStrongBuy],macdFastSlowSignals.MinFastMACD);
        return compositeDataSource;    
      }
    }
    public CompositeDataSource MACDFastWeakSell
    {
      get
      {
        if(null==signals||0==signals.Length||null==macdFastSlowSignals)return null;
        CompositeDataSource compositeDataSource = MACDModel.Signals(signals[(int)SignalIndicator.FastWeakSell],macdFastSlowSignals.MinFastMACD);
        return compositeDataSource;    
      }
    }
    public CompositeDataSource MACDFastStrongSell
    {
      get
      {
        if(null==signals||0==signals.Length||null==macdFastSlowSignals)return null;
        CompositeDataSource compositeDataSource = MACDModel.Signals(signals[(int)SignalIndicator.FastStrongSell],macdFastSlowSignals.MinFastMACD);
        return compositeDataSource;
      }
    }
// *********************************************************** C O M P O S I T E   S O U R C E S  M A C D ****************************************************
    public CompositeDataSource SignalSlow
    {
      get
      {
        if(null==macdFastSlowSignals)return null;
        CompositeDataSource compositeDataSource = MACDModel.SignalSlow(macdFastSlowSignals);
        return compositeDataSource;
      }
    }
    public CompositeDataSource MACDSlow
    {
      get
      {
        if(null==macdFastSlowSignals)return null;
        CompositeDataSource compositeDataSource = MACDModel.MACDSlow(macdFastSlowSignals);
        return compositeDataSource;
      }
    }
    public CompositeDataSource SignalFast
    {
      get
      {
        if(null==macdFastSlowSignals)return null;
        CompositeDataSource compositeDataSource = MACDModel.SignalFast(macdFastSlowSignals);
        return compositeDataSource;
      }
    }
    public CompositeDataSource MACDFast
    {
      get
      {
        if(null==macdFastSlowSignals)return null;
        CompositeDataSource compositeDataSource = MACDModel.MACDFast(macdFastSlowSignals);
        return compositeDataSource;
      }
    }
    public String TitleSlow
    {
      get
      {
        if (null == companyName || null == macdFastSlowSignals || 0 == macdFastSlowSignals.Count) return "";
        return companyName + " (" + symbol + ") " + Utility.DateTimeToStringMMHDDHYYYY(macdFastSlowSignals.FromDate) + " Thru " + Utility.DateTimeToStringMMHDDHYYYY(macdFastSlowSignals.ThruDate)+" \nMACD(12,26,9)";
      }
    }
    public String TitleFast
    {
      get
      {
        if (null == companyName || null == macdFastSlowSignals || 0 == macdFastSlowSignals.Count) return "";
        return companyName + " (" + symbol + ") " + Utility.DateTimeToStringMMHDDHYYYY(macdFastSlowSignals.FromDate) + " Thru " + Utility.DateTimeToStringMMHDDHYYYY(macdFastSlowSignals.ThruDate)+" \nMACD(8,17,9)";
      }
    }
    public Boolean Visibility
    {
      get { return false; }
    }
    public Boolean CheckBoxLegendVisible
    {
      get
      {
        return isLegendVisible;
      }
      set
      {
        isLegendVisible = value;
        base.OnPropertyChanged("CheckBoxLegendVisible");
        base.OnPropertyChanged("LegendVisible");
      }
    }
    public String LegendVisible
    {
      get
      {
        if (isLegendVisible) return "true";
        return "false";
      }
      set
      {
        isLegendVisible = Boolean.Parse(value);
        base.OnPropertyChanged("LegendVisible");
      }
    }
    public List<Int32> DayCounts
    {
      get { return dayCounts; }
    }
    public Int32 SelectedDayCount
    {
      get { return selectedDayCount; }
      set { selectedDayCount = value; base.OnPropertyChanged("SelectedDayCount"); }
    }
    public List<String> Symbols
    {
      get
      {
        return symbols;
      }
    }
    public String SelectedSymbol
    {
      get { return symbol; }
      set
      {
        if (value == symbol || String.IsNullOrEmpty(value)) return;
        symbol = value;
        base.OnPropertyChanged("SelectedSymbol");
      }
    }
    public List<String> WatchListNames
    {
      get
      {
        return watchLists;
      }
      set { ;}
    }
    public String SelectedWatchList
    {
      get { return selectedWatchList; }
      set { selectedWatchList = value; base.OnPropertyChanged("SelectedWatchList"); }
    }
    private void Refresh()
    {
      base.OnPropertyChanged("SelectedSymbol");
    }
    private Boolean CanRefresh
    {
      get { return true; }
    }
    public ICommand RefreshCommand
    {
      get
      {
        if (null == refreshCommand) refreshCommand = new RelayCommand(param => Refresh(), param => CanRefresh);
        return refreshCommand;
      }
    }
 }
}
