using MarketData.Utils;
using System;
using System.Collections.Generic;
using System.Linq;

namespace MarketData.Generator.CMMomentum
{
  public class ActivePositions : Dictionary<int, Positions>
  {
    public ActivePositions()
    {
    }
    public double GetExposure()
    {
      int count = Count;
      double exposure = 0.00;
      for (int slotIndex = 0; slotIndex < count; slotIndex++)
      {
        List<Position> positions = this[slotIndex];
        if (null == positions || 0 == positions.Count) continue;
        exposure += (from Position position in positions select position.Exposure).Sum();
      }
      return exposure;
    }

    public bool Remove(Position searchPosition)
    {
      List<int> keys = new List<int>(this.Keys);
      for (int index = 0; index < keys.Count; index++)
      {
        Positions positions = this[keys[index]];
        foreach (Position slotPosition in positions)
        {
          if (slotPosition == searchPosition)
          {
            positions.Remove(searchPosition);
            return true;
          }
        }
      }
      return false;
    }

    public Positions GetPositions()
    {
      Positions positionsCollection=new Positions();
      List<int> keys=new List<int>(this.Keys);
      Dictionary<String,String> symbols=new Dictionary<String,String>();
      for(int index=0;index<keys.Count;index++)
      {
        Positions positions=this[keys[index]];
        foreach(Position position in positions)
        {
          positionsCollection.Add(position);
        }
      }
      return positionsCollection;
    }

    public List<String> GetSymbols()
    {
      Dictionary<String, String> symbols = new Dictionary<String, String>();
      for (int slotIndex = 0; slotIndex < Count; slotIndex++)
      {
        List<Position> positions = this[slotIndex];
        if (null == positions || 0 == positions.Count) continue;
        for (int positionIndex = 0; positionIndex < positions.Count; positionIndex++)
        {
          Position position = positions[positionIndex];
          if (!symbols.ContainsKey(position.Symbol)) symbols.Add(position.Symbol, position.Symbol);
        }
      }
      return new List<String>(symbols.Keys);
    }

    public double GetMarketValue()
    {
      int count = Count;
      double marketValue = 0.00;
      for (int slotIndex = 0; slotIndex < count; slotIndex++)
      {
        List<Position> positions = this[slotIndex];
        if (null == positions || 0 == positions.Count) continue;
        marketValue += (from Position position in positions select position.MarketValue).Sum();
      }
      return marketValue;
    }

    public double GetGainLoss()
    {
      int count = Count;
      double marketValue = 0.00;
      double exposure = 0.00;
      for (int slotIndex = 0; slotIndex < count; slotIndex++)
      {
        List<Position> positions = this[slotIndex];
        if (null == positions || 0 == positions.Count) continue;
        exposure += (from Position position in positions select position.Exposure).Sum();
        marketValue += (from Position position in positions select position.MarketValue).Sum();
      }
      return marketValue - exposure;
    }

    public double GetGainLossPercent()
    {
      double exposure = GetExposure();
      double marketValue = GetMarketValue();
      if (0.00 == exposure) return exposure;
      return (marketValue - exposure) / exposure;
    }

    public void Display()
    {
      for (int slotIndex = 0; slotIndex < Count; slotIndex++)
      {
        Positions positions = this[slotIndex];
        DateTime purchaseDate = (from Position position in positions select position.PurchaseDate).Distinct().FirstOrDefault();
        MDTrace.WriteLine(LogLevel.DEBUG, String.Format("******************* B U Y S  F O R  {0} *****************", Utility.DateTimeToStringMMHDDHYYYY(purchaseDate)));
        positions.Display();
      }
    }

    public void AddFromNVPCollection(NVPCollection nvpCollection)
    {
      SlotPosition slotPosition = SlotPosition.FromNVPCollection(nvpCollection);
      if (!ContainsKey(slotPosition.Slot))
      {
        Add(slotPosition.Slot, new Positions());
      }
      this[slotPosition.Slot].Add(slotPosition.ToPosition());  
    }

    public List<NVPCollections> ToNVPCollections()
    {
      List<int> slots = new List<int>(Keys);
      List<NVPCollections> nvpCollectionsList = new List<NVPCollections>();
      foreach (int slot in slots)
      {
        Positions positions = this[slot];
        SlotPositions slotPositions = new SlotPositions(slot, positions);
        NVPCollections nvpCollections = slotPositions.ToNVPCollections();
        nvpCollectionsList.Add(nvpCollections);
      }
      return nvpCollectionsList;
    }
  }
}
