using System.Globalization;
using System.IO.Abstractions;
using Terminal.Gui.Resources;
namespace Terminal.Gui;
///
/// Wrapper for that contains additional information (e.g. )
/// and helper methods.
///
internal class FileSystemInfoStats
{
/* ---- Colors used by the ls command line tool ----
*
* Blue: Directory
* Green: Executable or recognized data file
* Cyan (Sky Blue): Symbolic link file
* Yellow with black background: Device
* Magenta (Pink): Graphic image file
* Red: Archive file
* Red with black background: Broken link
*/
private const long ByteConversion = 1024;
private static readonly List ExecutableExtensions = new () { ".EXE", ".BAT" };
private static readonly List ImageExtensions = new ()
{
".JPG",
".JPEG",
".JPE",
".BMP",
".GIF",
".PNG"
};
private static readonly string [] SizeSuffixes = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
/// Initializes a new instance of the class.
/// The directory of path to wrap.
///
public FileSystemInfoStats (IFileSystemInfo fsi, CultureInfo culture)
{
FileSystemInfo = fsi;
LastWriteTime = fsi.LastWriteTime;
if (fsi is IFileInfo fi)
{
MachineReadableLength = fi.Length;
HumanReadableLength = GetHumanReadableFileSize (MachineReadableLength, culture);
Type = fi.Extension;
}
else
{
HumanReadableLength = string.Empty;
Type = $"<{Strings.fdDirectory}>";
IsDir = true;
}
}
/// Gets the wrapped (directory or file).
public IFileSystemInfo FileSystemInfo { get; }
public string HumanReadableLength { get; }
public bool IsDir { get; }
/// Gets or Sets a value indicating whether this instance represents the parent of the current state (i.e. "..").
public bool IsParent { get; internal set; }
public DateTime? LastWriteTime { get; }
public long MachineReadableLength { get; }
public string Name => IsParent ? ".." : FileSystemInfo.Name;
public string Type { get; }
public bool IsExecutable ()
{
// TODO: handle linux executable status
return FileSystemInfo is IFileSystemInfo f
&& ExecutableExtensions.Contains (
f.Extension,
StringComparer.InvariantCultureIgnoreCase
);
}
public bool IsImage ()
{
return FileSystemInfo is IFileSystemInfo f
&& ImageExtensions.Contains (
f.Extension,
StringComparer.InvariantCultureIgnoreCase
);
}
private static string GetHumanReadableFileSize (long value, CultureInfo culture)
{
if (value < 0)
{
return "-" + GetHumanReadableFileSize (-value, culture);
}
if (value == 0)
{
return "0.0 B";
}
var mag = (int)Math.Log (value, ByteConversion);
double adjustedSize = value / Math.Pow (1000, mag);
return string.Format (culture.NumberFormat, "{0:n2} {1}", adjustedSize, SizeSuffixes [mag]);
}
}