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

namespace MarketData.Generator.Momentum
{
  public class ActivePositions : Dictionary<int,Positions>
  {
    public ActivePositions()
    {
    }
    public double GetExposure()
    {
      double exposure=0.00;
      List<int> keys = new List<int>(Keys);
      for(int index=0;index<keys.Count;index++)
      {
        List<Position> positions=this[keys[index]];
        if(null==positions||0==positions.Count)continue;
        exposure+=(from Position position in positions select position.Exposure).Sum();
      }
      return exposure;
    }
    public List<String> GetSymbols()
    {
      return SymbolsHeld();
    }
    public Position FindPosition(String symbol,DateTime purchaseDate)
    {
      Position foundPosition=null;
      List<int> keys=new List<int>(this.Keys);
      for(int index=0;index<keys.Count;index++)
      {
        Positions positions=this[keys[index]];
        foreach(Position position in positions)
        {
          if(position.Symbol.Equals(symbol)&&position.PurchaseDate.Date.Equals(purchaseDate.Date))
          {
            foundPosition=position;
            break;
          }
        }
      }
      return foundPosition;
    }
    public int FindSlotForPosition(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 position in positions)
        {
          if(position == searchPosition)return index;
        }
      }
      return -1;
    }

    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> 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++)
      {
        Positions positions = this[keys[index]];
        foreach (Position position in positions)
        {
          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;
      List<int> keys=new List<int>(this.Keys);
      for(int index=0;index<keys.Count;index++)
      {
        List<Position> positions=this[keys[index]];
        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;

      List<int> keys = new List<int>(this.Keys);
      for(int index=0;index<keys.Count;index++)
      {
        List<Position> positions=this[keys[index]];
        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()
    {
      List<int> keys = new List<int>(this.Keys);
      for(int index=0;index<keys.Count;index++)
      {
        Positions positions=this[keys[index]];
        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> keys=new List<int>(Keys);
      List<NVPCollections> nvpCollectionsList=new List<NVPCollections>();
      for(int index=0;index<keys.Count;index++)
      {
        Positions positions=this[keys[index]];
        SlotPositions slotPositions=new SlotPositions(keys[index],positions);
        NVPCollections nvpCollections=slotPositions.ToNVPCollections();
        nvpCollectionsList.Add(nvpCollections);
      }
      return nvpCollectionsList;
    }
  }
}
