using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MarketData.Generator.Momentum;
using System.IO;
using MarketData.Utils;

namespace MarketData.Generator.CMMomentum
{
  public class CMSessionParams
  {
    public DateTime LastUpdated { get; set; }
    public DateTime TradeDate { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime AnalysisDate { get; set; }
    public CMParams CMParams { get; set; }
    public ActivePositions ActivePositions { get; set; }
    public Positions AllPositions { get; set; }
    public double CashBalance { get; set; }
    public double NonTradeableCash { get; set; }
    public int Cycle { get; set; }

    // This gets AllPositions+Positions
    public Positions GetCombinedPositions()
    {
      Positions positions=new Positions();
      foreach(Position position in AllPositions) positions.Add(position);
      Positions activePositions=ActivePositions.GetPositions();
      foreach(Position position in activePositions) positions.Add(position);
      return positions;
    }
  }
  // *****************************************************************************
  public class CMSessionManager
  {
	  private static String SIGNATURE="CMSESSIONv1.00";
    public bool SaveSession(CMSessionParams sessionParams, String pathSessionFile)
    {
      try
      {
        if (null == pathSessionFile) return false;
        pathSessionFile = GetSessionFileName(pathSessionFile);
        FileStream outStream = new FileStream(pathSessionFile, FileMode.Create);
        StreamWriter streamWriter = new StreamWriter(outStream);
        streamWriter.WriteLine(SIGNATURE);
        streamWriter.WriteLine((new NVP("LastUpdated", sessionParams.LastUpdated.ToString())).ToString());
        streamWriter.WriteLine((new NVP("TradeDate", sessionParams.TradeDate.ToShortDateString())).ToString());
        streamWriter.WriteLine((new NVP("StartDate", sessionParams.StartDate.ToShortDateString())).ToString());
        streamWriter.WriteLine((new NVP("AnalysisDate", sessionParams.AnalysisDate.ToShortDateString())).ToString());
        streamWriter.WriteLine((new NVP("Cycle", sessionParams.Cycle.ToString())).ToString());
        streamWriter.WriteLine((new NVP("CashBalance", sessionParams.CashBalance.ToString())).ToString());
        streamWriter.WriteLine((new NVP("NonTradeableCash", sessionParams.NonTradeableCash.ToString())).ToString());
        NVPCollection configurationCollection = sessionParams.CMParams.ToNVPCollection();
        streamWriter.WriteLine(configurationCollection.ToString());
        List<NVPCollections> nvpCollectionsList = sessionParams.ActivePositions.ToNVPCollections();
        int totalPositions = 0;
        foreach (NVPCollections nvpCollections in nvpCollectionsList)
        {
          List<String> nvpCollectionsStringList = nvpCollections.ToList();
          totalPositions += nvpCollectionsStringList.Count;
        }
        streamWriter.WriteLine((new NVP("TotalActivePositions", totalPositions.ToString())).ToString());
        foreach (NVPCollections nvpCollections in nvpCollectionsList)
        {
          List<String> nvpCollectionsStringList = nvpCollections.ToList();
          foreach (String str in nvpCollectionsStringList)
          {
            streamWriter.WriteLine(str);
          }
        }
        NVPCollections allPositionsCollections = sessionParams.AllPositions.ToNVPCollections();
        List<String> nvpAllCollectionsStringList = allPositionsCollections.ToList();
        streamWriter.WriteLine((new NVP("TotalPositions", nvpAllCollectionsStringList.Count.ToString())).ToString());
        foreach (String str in nvpAllCollectionsStringList) streamWriter.WriteLine(str);
        streamWriter.Flush();
        outStream.Flush();
        streamWriter.Close();
        streamWriter.Dispose();
        outStream.Close();
        outStream.Dispose();
        return true;
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG, String.Format("{0}", exception.ToString()));
        return false;
      }
    }
    public static CMSessionParams RestoreSession(String pathSessionFile)
    {
      FileStream inStream = null;
      StreamReader streamReader = null;
      try
      {
        pathSessionFile = GetSessionFileName(pathSessionFile);
        if (!SessionAvailable(pathSessionFile)) return null;
        CMSessionParams sessionParams = new CMSessionParams();
        inStream = new FileStream(pathSessionFile, FileMode.Open);
        streamReader = new StreamReader(inStream);
        String versionInfo = streamReader.ReadLine();
        if (!versionInfo.StartsWith(SIGNATURE)) return null;
        double version = double.Parse(Utility.BetweenString(versionInfo, "v", null));
        if (1.00 != version) return null;
        NVP lastUpdated = new NVP(streamReader.ReadLine());
        NVP tradeDate = new NVP(streamReader.ReadLine());
        NVP startDate = new NVP(streamReader.ReadLine());
        NVP analysisDate = new NVP(streamReader.ReadLine());
        NVP cycle = new NVP(streamReader.ReadLine());
        NVP cashBalance = new NVP(streamReader.ReadLine());
        NVP nonTradeableCash = new NVP(streamReader.ReadLine());
        sessionParams.LastUpdated = lastUpdated.Get<DateTime>();
        sessionParams.TradeDate = tradeDate.Get<DateTime>();
        sessionParams.StartDate = startDate.Get<DateTime>();
        sessionParams.AnalysisDate = analysisDate.Get<DateTime>();
        sessionParams.Cycle = cycle.Get<int>();
        sessionParams.CashBalance = cashBalance.Get<double>();
        sessionParams.NonTradeableCash=nonTradeableCash.Get<double>();
        NVPCollection configurationCollection = new NVPCollection(streamReader.ReadLine());
        sessionParams.CMParams = CMParams.FromNVPCollection(configurationCollection);
        int totalActivePositions = (new NVP(streamReader.ReadLine())).Get<int>();
        sessionParams.ActivePositions = new ActivePositions();
        for (int positionIndex = 0; positionIndex < totalActivePositions; positionIndex++)
        {
          NVPCollection nvpCollection = new NVPCollection(streamReader.ReadLine());
          sessionParams.ActivePositions.AddFromNVPCollection(nvpCollection);
        }
        int totalPositions = (new NVP(streamReader.ReadLine())).Get<int>();
        NVPCollections nvpCollections = new NVPCollections();
        for (int positionIndex = 0; positionIndex < totalPositions; positionIndex++)
        {
          NVPCollection nvpCollection = new NVPCollection(streamReader.ReadLine());
          nvpCollections.Add(nvpCollection);
        }
        sessionParams.AllPositions = Positions.FromNVPCollections(nvpCollections);
        inStream.Close();
        inStream.Dispose();
        inStream = null;
        streamReader.Close();
        streamReader.Dispose();
        streamReader = null;
        return sessionParams;
      }
      finally
      {
        if (null != streamReader) streamReader.Close();
        if (null != inStream) inStream.Close();
      }
    }
    public static String GetSessionFileName(String pathSessionFile)
    {
      if (null == pathSessionFile) return null;
      String directory=Path.GetDirectoryName(pathSessionFile);
      if ("".Equals(directory)) directory = Directory.GetCurrentDirectory();
      return directory+"\\"+Path.GetFileNameWithoutExtension(pathSessionFile) + ".txt";
    }
    public static bool SessionAvailable(String pathSessionFile)
    {
      return IsValidSessionFile(pathSessionFile);
    }
    public static bool IsValidSessionFile(String pathSessionFile)
    {
      FileStream inStream = null;
      StreamReader streamReader = null;
      try
      {
        if (null == pathSessionFile) return false;
        pathSessionFile = pathSessionFile.ToLower();
        pathSessionFile = GetSessionFileName(pathSessionFile);
        if (!File.Exists(pathSessionFile)) return false;
        inStream = new FileStream(pathSessionFile, FileMode.Open);
        streamReader = new StreamReader(inStream);
        String versionInfo = streamReader.ReadLine();
        if (!versionInfo.StartsWith(SIGNATURE)) return false;
        double version = double.Parse(Utility.BetweenString(versionInfo, "v", null));
        if (1.00 != version) return false;
        return true;
      }
      catch (Exception)
      {
        return false;
      }
      finally
      {
        if (null != streamReader) streamReader.Close();
        if (null != inStream) inStream.Close();
      }
    }
  }
}
