using System;
using System.IO;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Reflection;
using MarketData;

namespace PortfolioManager.ViewModels
{
  public class WorkspaceViewModelPersistenceHolder
  {
    public WorkspaceViewModel Workspace { get; set; }
    public SaveParameters WorkspaceParameters { get; set; }
  }
  public class WorkspaceViewModelPersistenceCollection : List<WorkspaceViewModelPersistenceHolder>
  {
  }
  public class WorkspacePersistenceHelper
  {
    public static String PARAMS_FILE="saveparams.config";

    private WorkspacePersistenceHelper()
    {
    }
    
    public static void Save(String pathFileName, ObservableCollection<WorkspaceViewModel> workspaces)
    {
      try
      {
        StreamWriter streamWriter = null;
        FileStream outStream = null;
        if (null == workspaces || 0 == workspaces.Count) return;
        //        MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Writing {0} to {1}", pathFileName, Directory.GetCurrentDirectory()));
        if (!File.Exists(pathFileName)) streamWriter = File.CreateText(pathFileName);
        else
        {
          outStream = new FileStream(pathFileName, FileMode.Truncate);
          streamWriter = new StreamWriter(outStream);
        }
        foreach (WorkspaceViewModel workspaceViewModel in workspaces)
        {
          if (workspaceViewModel.CanPersist())
          {
            SaveParameters workspaceViewModelParams = workspaceViewModel.GetSaveParameters();
            if (null == workspaceViewModelParams) continue;
            streamWriter.WriteLine(workspaceViewModelParams.ToString());
          }
        }
        streamWriter.Flush();
        streamWriter.Close();
        streamWriter.Dispose();
      }
      catch (Exception exception)
      {
        Debug.Write(exception.ToString());
      }
    }
    
    public static void Load(String pathFileName, ObservableCollection<WorkspaceViewModel> workspaces, InstantiateWorkspace workspaceInstantiator)
    {
      try
      {
        Dictionary<int, SaveParameters> loadedItems = new Dictionary<int, SaveParameters>();
        WorkspaceViewModelPersistenceCollection workspaceViewModelPersistenceCollection = new WorkspaceViewModelPersistenceCollection();
        if (!File.Exists(PARAMS_FILE))
        {
          // MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Unable to load params file : {0}",PARAMS_FILE));
          return;
        }
        FileStream inStream = new FileStream(PARAMS_FILE, FileMode.Open);
        StreamReader streamReader = new StreamReader(inStream);
        String strLine = null;
        while (null != (strLine = streamReader.ReadLine()))
        {
          SaveParameters workspaceViewModelParams = null;
          try { workspaceViewModelParams = SaveParameters.Parse(strLine); }
          catch (Exception exception)
          {
            MDTrace.WriteLine(LogLevel.DEBUG, String.Format("Error parsing line from configuration file.  The line was : {0}", strLine));
            MDTrace.WriteLine(LogLevel.DEBUG, String.Format("The exception was : {0}", exception.ToString()));
            continue;
          }
          if (loadedItems.ContainsKey(workspaceViewModelParams.Key))
          {
            // MDTrace.WriteLine(LogLevel.DEBUG,"Item already loaded, details follow...");
            foreach (KeyValuePair<String, String> kvp in workspaceViewModelParams)
            {
              // MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Key:{0} Value:{1}",kvp.Key,kvp.Value));
            }
            continue;
          }
          else loadedItems.Add(workspaceViewModelParams.Key, workspaceViewModelParams);
          var itemType = from KeyValuePair<String, String> item in workspaceViewModelParams where item.Key.Equals("Type") select item;
          KeyValuePair<String, String> selectedItem = itemType.FirstOrDefault();
          WorkspaceViewModel workspaceViewModel = null;
          Type[] booleanTypes = new Type[1];
          booleanTypes[0] = typeof(bool);
          ConstructorInfo constructorInfo = Type.GetType(selectedItem.Value).GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, CallingConventions.HasThis, booleanTypes, null);
          if (null != constructorInfo) workspaceViewModel = (WorkspaceViewModel)Activator.CreateInstance(Type.GetType(selectedItem.Value), new object[] { true });
          else workspaceViewModel = (WorkspaceViewModel)Activator.CreateInstance(Type.GetType(selectedItem.Value));
          workspaceViewModel.WorkspaceInstantiator = workspaceInstantiator;
          WorkspaceViewModelPersistenceHolder workspaceViewModelPersistenceHolder = new WorkspaceViewModelPersistenceHolder();
          workspaceViewModelPersistenceHolder.Workspace = workspaceViewModel;
          workspaceViewModelPersistenceHolder.WorkspaceParameters = workspaceViewModelParams;
          workspaceViewModelPersistenceCollection.Add(workspaceViewModelPersistenceHolder);
        }
        streamReader.Close();
        for (int index = 0; index < workspaceViewModelPersistenceCollection.Count; index++)
        {
          WorkspaceViewModelPersistenceHolder workspaceViewModelPersistenceHolder = workspaceViewModelPersistenceCollection[index];
          if (index > 0) workspaceViewModelPersistenceHolder.Workspace.Referer = workspaceViewModelPersistenceCollection[index - 1].Workspace;
          workspaces.Add(workspaceViewModelPersistenceHolder.Workspace);
          workspaceViewModelPersistenceHolder.Workspace.SetSaveParameters(workspaceViewModelPersistenceHolder.WorkspaceParameters);
          if (index == workspaceViewModelPersistenceCollection.Count - 1)
          {
            // ICollectionView collectionView = CollectionViewSource.GetDefaultView(workspaces);
            // if (null != collectionView) collectionView.MoveCurrentTo(workspaceViewModelPersistenceHolder.Workspace);
          }
        }
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG, exception);
      }
    }
    
    public static WorkspaceViewModel Load(SaveParameters saveParams, ObservableCollection<WorkspaceViewModel> workspaces, InstantiateWorkspace workspaceInstantiator)
    {
      var itemType = from KeyValuePair<String, String> item in saveParams where item.Key.Equals("Type") select item;
      KeyValuePair<String, String> selectedItem = itemType.FirstOrDefault();
      WorkspaceViewModel workspaceViewModel = null;
      Type[] booleanTypes = new Type[1];
      booleanTypes[0] = typeof(bool);
      ConstructorInfo constructorInfo = Type.GetType(selectedItem.Value).GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, CallingConventions.HasThis, booleanTypes, null);
      if (null != constructorInfo) workspaceViewModel = (WorkspaceViewModel)Activator.CreateInstance(Type.GetType(selectedItem.Value), new object[] { true });
      else workspaceViewModel = (WorkspaceViewModel)Activator.CreateInstance(Type.GetType(selectedItem.Value));
      workspaceViewModel.WorkspaceInstantiator = workspaceInstantiator;
      WorkspaceViewModelPersistenceHolder workspaceViewModelPersistenceHolder = new WorkspaceViewModelPersistenceHolder();
      workspaceViewModelPersistenceHolder.Workspace = workspaceViewModel;
      workspaceViewModelPersistenceHolder.WorkspaceParameters = saveParams;
      workspaces.Add(workspaceViewModelPersistenceHolder.Workspace);
      workspaceViewModelPersistenceHolder.Workspace.SetSaveParameters(workspaceViewModelPersistenceHolder.WorkspaceParameters);
      // ICollectionView collectionView = CollectionViewSource.GetDefaultView(workspaces);
      // if (null != collectionView) collectionView.MoveCurrentTo(workspaceViewModelPersistenceHolder.Workspace);
      return workspaceViewModel;
    }
  }
  
  public class SaveParametersList : List<KeyValuePair<String, String>>
  {
    public int Key
    {
      get
      {
        StringBuilder sb = new StringBuilder();
        foreach (KeyValuePair<String, String> kvp in this)
        {
          sb.Append(kvp.Key).Append(",").Append(kvp.Value);
        }
        return sb.ToString().GetHashCode();
      }
    }
  }

  public class SaveParameters : SaveParametersList
  {
    public WorkspaceViewModel Referer { get; set; }

    public bool ContainsKey(String key)
    {
      foreach (KeyValuePair<String, String> item in this)
      {
        if (item.Key.Equals(key)) return true;
      }
      return false;
    }

    public override String ToString()
    {
      StringBuilder sb = new StringBuilder();
      for (int index = 0; index < Count; index++)
      {
        KeyValuePair<String, String> item = this[index];
        sb.Append(item.Key).Append(",").Append(item.Value);
        if (index < Count - 1) sb.Append(",");
      }
      return sb.ToString();
    }

    public static SaveParameters Parse(String strLine)
    {
      if (null == strLine) return null;
      String[] strArray = strLine.Split(',');
      if (null == strArray || 0 == strArray.Length) return null;
      SaveParameters saveParameters = new SaveParameters();
      for (int index = 0; index < strArray.Length; index += 2)
      {
        KeyValuePair<String, String> savedParameter = new KeyValuePair<String, String>(strArray[index], strArray[index + 1]);
        saveParameters.Add(savedParameter);
      }
      return saveParameters;
    }
    
  }
}
