using System.Collections.Generic;
using System.Linq;
using Eremex.AvaloniaUI.Charts;
using MarketData.MarketDataModel;
using MarketData.Numerical;
using PortfolioManager.DataSeriesViewModels;

namespace PortfolioManager.Models
{
  public class BollingerBandModel
  {
    private BollingerBandModel()
    {
    }

    public static CompositeDataSource Empty()
    {
      CompositeDataSource compositeDataSource = new CompositeDataSource()
      {
        DataAdapter = new SortedDateTimeDataAdapter()
      };
      return compositeDataSource;
    }

    public static CompositeDataSource SMAN(BollingerBands bollingerBands)
    {
      if (null == bollingerBands || 0 == bollingerBands.Count) return Empty();
      SortedDateTimeDataAdapter sortedDateTimeDataAdapter = new SortedDateTimeDataAdapter();
      List<BollingerBandElement> sortedBollingerBands = bollingerBands.OrderBy(x => x.Date).ToList();
      foreach (BollingerBandElement bollingerBandElement in sortedBollingerBands)
      {
        sortedDateTimeDataAdapter.Add(bollingerBandElement.Date, bollingerBandElement.SMAN);
      }
      CompositeDataSource compositeDataSource = new CompositeDataSource()
      {
        DataAdapter = sortedDateTimeDataAdapter
      };
      return compositeDataSource;
    }

    public static CompositeDataSource K(BollingerBands bollingerBands)
    {
      if (null == bollingerBands || 0 == bollingerBands.Count) return Empty();
      SortedDateTimeDataAdapter sortedDateTimeDataAdapter = new SortedDateTimeDataAdapter();
      List<BollingerBandElement> sortedBollingerBands = bollingerBands.OrderBy(x => x.Date).ToList();
      foreach (BollingerBandElement bollingerBandElement in sortedBollingerBands)
      {
        sortedDateTimeDataAdapter.Add(bollingerBandElement.Date, bollingerBandElement.K);
      }
      CompositeDataSource compositeDataSource = new CompositeDataSource()
      {
        DataAdapter = sortedDateTimeDataAdapter
      };
      return compositeDataSource;
    }

    public static CompositeDataSource KL1(BollingerBands bollingerBands)
    {
      if (null == bollingerBands || 0 == bollingerBands.Count) return Empty();
      SortedDateTimeDataAdapter sortedDateTimeDataAdapter = new SortedDateTimeDataAdapter();
      List<BollingerBandElement> sortedBollingerBands = bollingerBands.OrderBy(x => x.Date).ToList();
      foreach (BollingerBandElement bollingerBandElement in sortedBollingerBands)
      {
        sortedDateTimeDataAdapter.Add(bollingerBandElement.Date, bollingerBandElement.KL1);
      }
      CompositeDataSource compositeDataSource = new CompositeDataSource()
      {
        DataAdapter = sortedDateTimeDataAdapter
      };
      return compositeDataSource;
    }

    public static CompositeDataSource L(BollingerBands bollingerBands)
    {
      if (null == bollingerBands || 0 == bollingerBands.Count) return Empty();
      SortedDateTimeDataAdapter sortedDateTimeDataAdapter = new SortedDateTimeDataAdapter();
      List<BollingerBandElement> sortedBollingerBands = bollingerBands.OrderBy(x => x.Date).ToList();
      foreach (BollingerBandElement bollingerBandElement in sortedBollingerBands)
      {
        sortedDateTimeDataAdapter.Add(bollingerBandElement.Date, bollingerBandElement.L);
      }
      CompositeDataSource compositeDataSource = new CompositeDataSource()
      {
        DataAdapter = sortedDateTimeDataAdapter
      };
      return compositeDataSource;
    }

    public static CompositeDataSource LP1(BollingerBands bollingerBands)
    {
      if (null == bollingerBands || 0 == bollingerBands.Count) return Empty();
      SortedDateTimeDataAdapter sortedDateTimeDataAdapter = new SortedDateTimeDataAdapter();
      List<BollingerBandElement> sortedBollingerBands = bollingerBands.OrderBy(x => x.Date).ToList();
      foreach (BollingerBandElement bollingerBandElement in sortedBollingerBands)
      {
        sortedDateTimeDataAdapter.Add(bollingerBandElement.Date, bollingerBandElement.LP1);
      }
      CompositeDataSource compositeDataSource = new CompositeDataSource()
      {
        DataAdapter = sortedDateTimeDataAdapter
      };
      return compositeDataSource;
    }

    public static CompositeDataSource High(BollingerBands bollingerBands)
    {
      if (null == bollingerBands || 0 == bollingerBands.Count) return Empty();
      SortedDateTimeDataAdapter sortedDateTimeDataAdapter = new SortedDateTimeDataAdapter();
      List<BollingerBandElement> sortedBollingerBands = bollingerBands.OrderBy(x => x.Date).ToList();
      foreach (BollingerBandElement bollingerBandElement in sortedBollingerBands)
      {
        sortedDateTimeDataAdapter.Add(bollingerBandElement.Date, bollingerBandElement.High);
      }
      CompositeDataSource compositeDataSource = new CompositeDataSource()
      {
        DataAdapter = sortedDateTimeDataAdapter
      };
      return compositeDataSource;
    }

    public static CompositeDataSource Low(BollingerBands bollingerBands)
    {
      if (null == bollingerBands || 0 == bollingerBands.Count) return Empty();
      SortedDateTimeDataAdapter sortedDateTimeDataAdapter = new SortedDateTimeDataAdapter();
      List<BollingerBandElement> sortedBollingerBands = bollingerBands.OrderBy(x => x.Date).ToList();
      foreach (BollingerBandElement bollingerBandElement in sortedBollingerBands)
      {
        sortedDateTimeDataAdapter.Add(bollingerBandElement.Date, bollingerBandElement.Low);
      }
      CompositeDataSource compositeDataSource = new CompositeDataSource()
      {
        DataAdapter = sortedDateTimeDataAdapter
      };
      return compositeDataSource;
    }

    public static CompositeDataSource Close(BollingerBands bollingerBands)
    {
      if (null == bollingerBands || 0 == bollingerBands.Count) return Empty();
      SortedDateTimeDataAdapter sortedDateTimeDataAdapter = new SortedDateTimeDataAdapter();
      List<BollingerBandElement> sortedBollingerBands = bollingerBands.OrderBy(x => x.Date).ToList();
      foreach (BollingerBandElement bollingerBandElement in sortedBollingerBands)
      {
        sortedDateTimeDataAdapter.Add(bollingerBandElement.Date, bollingerBandElement.Close);
      }
      CompositeDataSource compositeDataSource = new CompositeDataSource()
      {
        DataAdapter = sortedDateTimeDataAdapter
      };
      return compositeDataSource;
    }

    public static CompositeDataSource Volume(BollingerBands bollingerBands)
    {
      if (null == bollingerBands || 0 == bollingerBands.Count) return Empty();
      SortedDateTimeDataAdapter sortedDateTimeDataAdapter = new SortedDateTimeDataAdapter();
      List<BollingerBandElement> sortedBollingerBands = bollingerBands.OrderBy(x => x.Date).ToList();
      foreach (BollingerBandElement bollingerBandElement in sortedBollingerBands)
      {
        sortedDateTimeDataAdapter.Add(bollingerBandElement.Date, bollingerBandElement.Volume);
      }
      CompositeDataSource compositeDataSource = new CompositeDataSource()
      {
        DataAdapter = sortedDateTimeDataAdapter
      };
      return compositeDataSource;
    }

// The least squares might be in the wrong order if the Bollinger band was already sorted by date
    public static CompositeDataSource LeastSquares(BollingerBands bollingerBands)
    {
      if (null == bollingerBands || 0 == bollingerBands.Count) return Empty();
      LeastSquaresResult leastSquaresResult = bollingerBands.LeastSquaresFitClose();
      SortedDateTimeDataAdapter sortedDateTimeDataAdapter = new SortedDateTimeDataAdapter();
      List<BollingerBandElement> sortedBollingerBands = bollingerBands.OrderBy(x => x.Date).ToList();
      for (int index = 0; index < sortedBollingerBands.Count; index++)
      {
        BollingerBandElement element = sortedBollingerBands[index];
        int leastSquaresIndex = (leastSquaresResult.LeastSquares.Length - 1) - index;
        sortedDateTimeDataAdapter.Add(element.Date, leastSquaresResult.LeastSquares[leastSquaresIndex]);
      }
      CompositeDataSource compositeDataSource = new CompositeDataSource()
      {
        DataAdapter = sortedDateTimeDataAdapter
      };
      return compositeDataSource;
    }
  }
}
