using System;
using System.Collections.Generic;
using System.Linq;
using TradeBlotter.Views;
using MarketData.MarketDataModel;
using MarketData.Generator;
using Microsoft.Research.DynamicDataDisplay.DataSources;
using MarketData.Numerical;
using MarketData.MarketDataModel.GainLoss;

namespace TradeBlotter.Model
{
  public class GainLossModel
  {
    private GainLossModel()
    {
    }
    public static CompositeDataSource CreateCompositeDataSource(DateTime xSource,double ySource)
    {
      CompositeDataSource compositeDataSource;
      var xData=new EnumerableDataSource<DateTime>(new DateTime[] { xSource });
      xData.SetXMapping(x => (x.Ticks/10000000000.0));
      var yData=new EnumerableDataSource<double>(new double[] { ySource });
      yData.SetYMapping(y => y);
      compositeDataSource=xData.Join(yData);
      return compositeDataSource;
    }
    public static CompositeDataSource Price(Price price)
    {
      if (null == price) return null;
      CompositeDataSource compositeDataSource;
      var xData = new EnumerableDataSource<DateTime>(new DateTime[]{price.Date});
      xData.SetXMapping(x => (x.Ticks / 10000000000.0));
      var yData = new EnumerableDataSource<double>(new double[]{price.Close});
      yData.SetYMapping(y => y);
      compositeDataSource = xData.Join(yData);
      return compositeDataSource;
    }
// *************************************************************** A C T I V E   G A I N  / L O S S   C O M P O N E N T S ***************************************
    // This is the active gain/loss as number or percent.
    public static CompositeDataSource GainLoss(ModelPerformanceSeries gainLossList,bool useGainLoss)
    {
      if(null==gainLossList) return null;
      CompositeDataSource compositeDataSource;
      var xData=new EnumerableDataSource<DateTime>(gainLossList.Select(x => x.Date.Date));
      xData.SetXMapping(x => (x.Ticks/10000000000.0));
      var yData=new EnumerableDataSource<double>(gainLossList.Select(y => useGainLoss?y.CumulativeGainLoss:y.CumProdMinusOne*100.00));
      yData.SetYMapping(y => y);
      compositeDataSource=xData.Join(yData);
      return compositeDataSource;
    }

// This is the active gain/loss as number or percent.
    public static CompositeDataSource GainLoss(GainLossCompoundModelCollection gainLossList,bool useGainLoss)
    {
      if (null == gainLossList) return null;
      CompositeDataSource compositeDataSource;
      var xData = new EnumerableDataSource<DateTime>(gainLossList.Select(x => x.Date.Date));
      xData.SetXMapping(x => (x.Ticks / 10000000000.0));
      var yData = new EnumerableDataSource<double>(gainLossList.Select(y => useGainLoss?y.ActiveGainLoss:y.ActiveGainLossPercent));
      yData.SetYMapping(y => y);
      compositeDataSource = xData.Join(yData);
      return compositeDataSource;
    }
// This is the least squares composite data source based on the active gain/loss
    public static CompositeDataSource LeastSquares(GainLossCompoundModelCollection gainLossList,bool useGainLoss)
    {
      if (null == gainLossList) return null;
      CompositeDataSource compositeDataSource;
      var xData = new EnumerableDataSource<DateTime>(gainLossList.Select(x => x.Date.Date));
      xData.SetXMapping(x => (x.Ticks / 10000000000.0));
      LeastSquaresResult leastSquaresResult=LeastSquaresFit(gainLossList,useGainLoss);
      var yData = new EnumerableDataSource<double>(leastSquaresResult.LeastSquares);
      yData.SetYMapping(y => y);
      compositeDataSource = xData.Join(yData);
      return compositeDataSource;
    }
// This is the LeastSquares fit based on the active gain/loss
		public static LeastSquaresResult LeastSquaresFit(GainLossCompoundModelCollection gainLossList,bool useGainLoss)
		{
			double[] values=null;
      if(useGainLoss)values=(from GainLossCompoundModel gainLoss in gainLossList select gainLoss.ActiveGainLoss).ToList().ToArray();
      else values=(from GainLossCompoundModel gainLoss in gainLossList select gainLoss.ActiveGainLossPercent).ToList().ToArray();
			LeastSquaresResult leastSquaresResult=Numerics.LeastSquares(values);
			return leastSquaresResult;
		}
// *************************************************************** T O T A L  G A I N  / L O S S   C O M P O N E N T S ***************************************
// This is the total gain loss as number or percent
    public static CompositeDataSource TotalGainLoss(GainLossCompoundModelCollection gainLossList,bool useGainLoss)
    {
      if (null == gainLossList) return null;
      CompositeDataSource compositeDataSource;
      var xData = new EnumerableDataSource<DateTime>(gainLossList.Select(x => x.Date.Date));
      xData.SetXMapping(x => (x.Ticks / 10000000000.0));
      var yData = new EnumerableDataSource<double>(gainLossList.Select(y => useGainLoss?y.TotalGainLoss:y.TotalGainLossPercent));
      yData.SetYMapping(y => y);
      compositeDataSource = xData.Join(yData);
      return compositeDataSource;
    }
// This is the least squares composite data source based on the total gain/loss
    public static CompositeDataSource TotalLeastSquares(GainLossCompoundModelCollection gainLossList,bool useGainLoss)
    {
      if (null == gainLossList) return null;
      CompositeDataSource compositeDataSource;
      var xData = new EnumerableDataSource<DateTime>(gainLossList.Select(x => x.Date.Date));
      xData.SetXMapping(x => (x.Ticks / 10000000000.0));
      LeastSquaresResult leastSquaresResult=TotalLeastSquaresFit(gainLossList,useGainLoss);
      var yData = new EnumerableDataSource<double>(leastSquaresResult.LeastSquares);
      yData.SetYMapping(y => y);
      compositeDataSource = xData.Join(yData);
      return compositeDataSource;
    } 
// This is the LeastSquares fit based on the total gain/loss
		public static LeastSquaresResult TotalLeastSquaresFit(GainLossCompoundModelCollection gainLossList,bool useGainLoss)
		{
			double[] values=null;
      if(useGainLoss)values=(from GainLossCompoundModel gainLoss in gainLossList select gainLoss.TotalGainLoss).ToList().ToArray();
      else values=(from GainLossCompoundModel gainLoss in gainLossList select gainLoss.TotalGainLossPercent).ToList().ToArray();
			LeastSquaresResult leastSquaresResult=Numerics.LeastSquares(values);
			return leastSquaresResult;
		}
 
  }
}
