using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;

namespace Addison_Wesley.Codebook.Filesystem
{
   public class RecycleBin
   {
      /// <summary>
      /// Obsahuje informace o koši
      /// </summary>
      public class RecycleBinInfo
      {
         /// <summary>
         /// Velikost všech souborů v koši
         /// </summary>
         public long Size = 0;

         /// <summary>
         /// Počet souborů v koši
         /// </summary>
         public long Count = 0;
      }

      /* Struktura, v níž SHQueryRecycleBin vrací zjištěné informace */
      [StructLayout(LayoutKind.Sequential, Pack = 1)]
      private struct SHQUERYRBINFO
      {
         public int cbSize;
         public long i64Size;
         public long i64NumItems;
      }

      /* Deklarace potřebných funkcí a konstant z API */
      [DllImport("shell32.dll", CharSet = CharSet.Auto)]
      static extern int SHQueryRecycleBin(string rootPath,
         ref SHQUERYRBINFO shQueryRBInfo);

      [DllImport("Kernel32.dll")]
      private static extern uint GetDriveType(string lpRootPathName);

      private const uint DRIVE_FIXED = 3;

      /// <summary>
      /// Vrátí velikost a počet souborů v koši na zadaném disku
      /// </summary>
      /// <param name="rootPath">Kořenový adresář disku</param>
      /// <returns>vrátí instanci typu RecycleBinInfo</returns>
      public static RecycleBinInfo GetRecycleBinInfo(string rootPath)
      {
          // Určení diskových zařízení, která se mají vyšetřit 
         List<string> drives = new List<string>();
         if (rootPath != null && rootPath != "")
         {
            drives.Add(rootPath);
         }
         else
         {
            // Zjištění všech oddílů pevných disků 
            string[] logicalDrives = Environment.GetLogicalDrives();
            for (int i = 0; i < logicalDrives.Length; i++)
            {
               if (GetDriveType(logicalDrives[i]) == DRIVE_FIXED)
               {
                  drives.Add(logicalDrives[i]);
               }
            }
         }

         // Vytvoření instance typu RecycleBinInfo pro výsledek 
         // a struktury SHQUERYRBINFO
         RecycleBinInfo rbi = new RecycleBinInfo();
         SHQUERYRBINFO shQueryRBInfo = new SHQUERYRBINFO();

         // Definice velikosti struktury, aby byla při zápisu 
         // známa funkci z API 
         shQueryRBInfo.cbSize = Marshal.SizeOf(typeof(SHQUERYRBINFO));

         // Prochjdeme všechna disková zařízení 
         for (int i = 0; i < drives.Count; i++)
         {
            // Volání funkce SHQueryRecycleBin a vyhodnocení případných chyb
            int result = SHQueryRecycleBin(drives[i] + "\x0",
               ref shQueryRBInfo);
            if (result == 0)
            {
               // Kein Fehler: Die gelesenen Daten mit dem Ergebnis addieren
               rbi.Size += shQueryRBInfo.i64Size;
               rbi.Count += shQueryRBInfo.i64NumItems;
            }
            else
            {
                // Nedošlo k žádné chybě: Načtená data přičíst k výsledku
               throw new Exception(String.Format(
                  "Chyba 0x{0:X} při vyšetřování koše", result));
            }
         }

         return rbi;
      }
   }
}
