context: /**
  \author		Shestakov Mikhail aka MIKE
  \date		02.02.2013 (c)Andrey Korotkov
  
  This file is a part of DGLE project and is distributed
  under the terms of the GNU Lesser General Public License.
  See "DGLE.h" for more details.
  */
  using System;
  using System.IO;
  using System.Runtime.InteropServices;
  using System.Collections;
  using System.Collections.Generic;
  using System.Linq;
  using DGLE;
  
  namespace Packer
  {
  	public static class Packer
  	{
  		public class Item
  		{
  			public string Name { get; set; }
  
  			public string Directory { get; set; }
  
  			public string FullName
  			{
  				get { return Directory + Name + (IsFolder ? @"\" : ""); }
  			}
  
  			public bool IsFolder { get; set; }
  
  			public bool IsRoot { get; private set; }
  
  			public string HDDPath { get; set; }
  
  			public Item()
  			{
  				this.IsFolder = false;
  				this.IsRoot = false;
  			}
  
  			public Item(bool isRoot)
  			{
  				this.Name = "..";
  				this.IsFolder = true;
  				this.IsRoot = isRoot;
  			}
  
  			public Item(string hddPath)
  			{
  				this.HDDPath = hddPath;
  				this.Name = Path.GetFileName(this.HDDPath);
  				this.Directory = @"";
  				this.IsFolder = System.IO.Directory.Exists(this.HDDPath);
  				this.IsRoot = false;
  			}
  		}
  
  		public class VirtualFileSystem
  		{
  			private IFileSystem fileSystem;
  
  			public string Extension { get; private set; }
  
  			public string Description { get; private set; }
  
  			public string LastError { get; private set; }
  
  			public VirtualFileSystem(IFileSystem fileSystem, string extension, string description)
  			{
  				this.fileSystem = fileSystem;
  				this.Extension = extension;
  				this.Description = description;
  			}
  
  			public void New()
  			{
  				Console.WriteLine("Create");
  				TVariant arg = TVariant.Zero;
  				fileSystem.ExecuteTextCommand("create", ref arg);
  				GetLastError(arg);
  			}
  
  			public bool Open(string filename)
  			{
  				Console.WriteLine("Open " + filename);
  				TVariant arg = TVariant.Zero;
  				fileSystem.ExecuteTextCommand(
  					String.Format("{0} {1}", "open", filename),
  					ref arg);
  				GetLastError(arg);
  				return (bool)arg;
  			}
  
  			public string[] ListFiles()
  			{
  				Console.WriteLine("List");
  				
  				string filenames = MarshalUtils.MarshalString((pnt, length) => { 
  					fileSystem.ExecuteTextCommandEx("list", pnt, out length);
  					return length;
  				});
  				
  				Console.WriteLine(filenames);
  				return filenames.Split(';');
  			}
  
  			public bool Save(string filename)
  			{
  				if (Path.HasExtension(filename))
  					filename = Path.ChangeExtension(filename, "." + Extension.ToLower());
  				else
  					filename += "." + Extension.ToLower();
  
  				Console.WriteLine("Save as " + filename);
  				TVariant arg = TVariant.Zero;
  				fileSystem.ExecuteTextCommand(
  					String.Format("{0} {1}", "save", filename),
  					ref arg);
  				GetLastError(arg);
  				return (bool)arg;
  			}
  
  			public void Close()
  			{
  				Console.WriteLine("Close");
  				TVariant arg = TVariant.Zero;
  				fileSystem.ExecuteTextCommand("close", ref arg);
  				GetLastError(arg);
  			}
  
  			public bool Add(Item item)
  			{
  				Console.WriteLine("Add " + item.HDDPath);
  				Console.WriteLine("As " + item.FullName);
  				TVariant arg = TVariant.Zero;
  				fileSystem.ExecuteTextCommand(
  					String.Format("{0} {1};{2}", "add", item.HDDPath, item.Directory),
  					ref arg);
  				GetLastError(arg);
  				return (bool)arg;
  			}
  
  			public bool Remove(Item item)
  			{
  				Console.WriteLine("Remove " + item.FullName);
  				TVariant arg = TVariant.Zero;
  				fileSystem.ExecuteTextCommand(
  					String.Format("{0} {1}", "remove", item.FullName),
  					ref arg);
  				GetLastError(arg);
  				return (bool)arg;
  			}
  
  			public bool Extract(Item item, string newFilename)
  			{
  				Console.WriteLine("Extract " + item.FullName);
  				Console.WriteLine("To " + newFilename);
  				TVariant arg = TVariant.Zero;
  				fileSystem.ExecuteTextCommand(
  					String.Format("{0} {1};{2}", "extract", item.FullName, newFilename),
  					ref arg);
  				GetLastError(arg);
  				return (bool)arg;
  			}
  
  			private void GetLastError(TVariant arg)
  			{
  				if ((bool)arg)
  				{
  					LastError = "";
  					return;
  				}
  				LastError = MarshalUtils.MarshalString((pnt, length) =>
  				{ 
  					fileSystem.ExecuteTextCommandEx("last_error", pnt, out length);
  					return length;
  				});
  				Console.WriteLine(LastError);
  			}
  		}
  
  		public static Dictionary<String, VirtualFileSystem> SupportedFileSystems { get; private set; }
  
  		public static string[] SupportedExtensions
  		{
  			get { return SupportedFileSystems.Keys.ToArray(); }
  		}
  
  		public static void Init()
  		{
  			IEngineSubSystem subSystem;
  			Program.Core.GetSubSystem(E_ENGINE_SUB_SYSTEM.ESS_FILE_SYSTEM, out subSystem);
  			IMainFileSystem mainFileSystem = subSystem as DGLE.IMainFileSystem;
  
  			String[] registredFileSystems = MarshalUtils.MarshalString((pnt, length) =>
  			{
  				mainFileSystem.GetRegisteredVirtualFileSystems(pnt, out length);
  				return length;
  			}).Split(';').ToList().Where(name => name.Trim().Length > 0).ToArray();
  
  			SupportedFileSystems = new Dictionary<string, VirtualFileSystem>(registredFileSystems.Length);
  			registredFileSystems.ToList().ForEach(ext =>
  			{
  				IFileSystem fileSystem;
  				mainFileSystem.GetVirtualFileSystem(ext, out fileSystem);
  
  
gt: 				string desc = MarshalUtils.MarshalString((pnt, length) =>