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

namespace MarketData.Generator.MGSHMomentum
{
  public class MGSHActivePositions : Dictionary<int,MGSHPositions>
  {
    public MGSHActivePositions()
    {
    }

    public int GetMaxSlotNumber()
    {
      List<int> keys = new List<int>(Keys);
      if(0 == keys.Count)
      {
        return -1;   // if there are no slots then return -1
      }
      return keys.Max();
    }

    public int GetCount()
    {
      int positionCount=0;
      List<int> keys = new List<int>(Keys);
      for(int index=0;index<keys.Count;index++)
      {
        List<MGSHPosition> positions=this[keys[index]];
        if(null==positions||0==positions.Count)continue;
        positionCount+=positions.Count;
      }
      return positionCount;
    }

    public double GetExposure()
    {
      double exposure=0.00;
      List<int> keys = new List<int>(Keys);
      for(int index=0;index<keys.Count;index++)
      {
        List<MGSHPosition> positions=this[keys[index]];
        if(null==positions||0==positions.Count)continue;
        exposure+=(from MGSHPosition position in positions select position.Exposure).Sum();
      }
      return exposure;
    }
    public List<String> GetSymbols()
    {
      return SymbolsHeld();
    }
    public MGSHPosition FindPosition(String symbol,DateTime purchaseDate)
    {
      MGSHPosition foundPosition=null;
      List<int> keys=new List<int>(this.Keys);
      for(int index=0;index<keys.Count;index++)
      {
        MGSHPositions positions=this[keys[index]];
        foreach(MGSHPosition position in positions)
        {
          if(position.Symbol.Equals(symbol)&&position.PurchaseDate.Date.Equals(purchaseDate.Date))
          {
            foundPosition=position;
            break;
          }
        }
      }
      return foundPosition;
    }
    public int FindSlotForPosition(MGSHPosition searchPosition)
    {
      List<int> keys=new List<int>(this.Keys);
      for(int index=0;index<keys.Count;index++)
      {
        MGSHPositions positions=this[keys[index]];
        foreach(MGSHPosition position in positions)
        {
          if(position == searchPosition)return index;
        }
      }
      return -1;
    }

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

    public MGSHPositions GetPositions()
    {
      MGSHPositions positionsCollection=new MGSHPositions();
      List<int> keys=new List<int>(this.Keys);
      Dictionary<String,String> symbols=new Dictionary<String,String>();
      for(int index=0;index<keys.Count;index++)
      {
        MGSHPositions positions=this[keys[index]];
        foreach(MGSHPosition position in positions)
        {
          positionsCollection.Add(position);
        }
      }
      return positionsCollection;
    }
    public List<String> SymbolsHeld()
    {
      List<int> keys = new List<int>(this.Keys);
      Dictionary<String, String> symbols = new Dictionary<String, String>();
      for (int index = 0; index < keys.Count; index++)
      {
        MGSHPositions positions = this[keys[index]];
        foreach (MGSHPosition position in positions)
        {
          if (!symbols.ContainsKey(position.Symbol)) symbols.Add(position.Symbol, position.Symbol);
        }
      }
      return new List<String>(symbols.Keys);
    }
    public double GetMarketValue()
    {
      double marketValue=0.00;
      List<int> keys=new List<int>(this.Keys);
      for(int index=0;index<keys.Count;index++)
      {
        List<MGSHPosition> positions=this[keys[index]];
        if(null==positions||0==positions.Count)continue;
        marketValue+=(from MGSHPosition position in positions select position.MarketValue).Sum();
      }
      return marketValue;
    }
    public double GetGainLoss()
    {
      double marketValue=0.00;
      double exposure=0.00;

      List<int> keys = new List<int>(this.Keys);
      for(int index=0;index<keys.Count;index++)
      {
        List<MGSHPosition> positions=this[keys[index]];
        if(null==positions||0==positions.Count)continue;
        exposure+=(from MGSHPosition position in positions select position.Exposure).Sum();
        marketValue+=(from MGSHPosition 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()
    {
      List<int> keys = new List<int>(this.Keys);
      for(int index=0;index<keys.Count;index++)
      {
        MGSHPositions positions=this[keys[index]];
        DateTime purchaseDate=(from MGSHPosition 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)
    {
      MGSHSlotPosition slotPosition=MGSHSlotPosition.FromNVPCollection(nvpCollection);
      if(!ContainsKey(slotPosition.Slot))
      {
        Add(slotPosition.Slot,new MGSHPositions());
      }
      this[slotPosition.Slot].Add(slotPosition.ToPosition());
    }
    public List<NVPCollections> ToNVPCollections()
    {
      List<int> keys=new List<int>(Keys);
      List<NVPCollections> nvpCollectionsList=new List<NVPCollections>();
      for(int index=0;index<keys.Count;index++)
      {
        MGSHPositions positions=this[keys[index]];
        MGSHSlotPositions slotPositions=new MGSHSlotPositions(keys[index],positions);
        NVPCollections nvpCollections=slotPositions.ToNVPCollections();
        nvpCollectionsList.Add(nvpCollections);
      }
      return nvpCollectionsList;
    }
  }
}
