using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.IO.Abstractions;
using System.Linq;
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 string [] SizeSuffixes = { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
private static readonly List ImageExtensions = new List { ".JPG", ".JPEG", ".JPE", ".BMP", ".GIF", ".PNG" };
private static readonly List ExecutableExtensions = new List { ".EXE", ".BAT" };
///
/// Initializes a new instance of the class.
///
/// The directory of path to wrap.
///
public FileSystemInfoStats (IFileSystemInfo fsi, CultureInfo culture)
{
this.FileSystemInfo = fsi;
this.LastWriteTime = fsi.LastWriteTime;
if (fsi is IFileInfo fi) {
this.MachineReadableLength = fi.Length;
this.HumanReadableLength = GetHumanReadableFileSize (this.MachineReadableLength, culture);
this.Type = fi.Extension;
} else {
this.HumanReadableLength = string.Empty;
this.Type = "dir";
}
}
///
/// Gets the wrapped (directory or file).
///
public IFileSystemInfo FileSystemInfo { get; }
public string HumanReadableLength { get; }
public long MachineReadableLength { get; }
public DateTime? LastWriteTime { get; }
public string Type { 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 string Name => this.IsParent ? ".." : this.FileSystemInfo.Name;
public bool IsDir ()
{
return this.Type == "dir";
}
public bool IsImage ()
{
return this.FileSystemInfo is IFileSystemInfo f &&
ImageExtensions.Contains (
f.Extension,
StringComparer.InvariantCultureIgnoreCase);
}
public bool IsExecutable ()
{
// TODO: handle linux executable status
return this.FileSystemInfo is IFileSystemInfo f &&
ExecutableExtensions.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 bytes";
}
int mag = (int)Math.Log (value, ByteConversion);
double adjustedSize = value / Math.Pow (1000, mag);
return string.Format (culture.NumberFormat,"{0:n2} {1}", adjustedSize, SizeSuffixes [mag]);
}
}
}