/* Copying and distribution of this file, with or without modification,
 * are permitted in any medium without royalty provided the copyright
 * notice and this notice are preserved.  This file is offered as-is,
 * without any warranty.
 */

import std.conv : octal;
import std.stdio;
import std.format;
import std.string : leftJustify;
import amalthea.dataprocessing : isAmong;
import amalthea.fs, amalthea.sys, amalthea.time;

import core.sys.posix.sys.stat : S_IFMT;

int main(string[] args) {
    immutable colLen1 = 27;

    foreach(arg; args[1 .. $]) {
        auto stx = FileStat(arg);
        writeln("  File: ", stx.filepath);
        write(format!"  Size: %d"(stx.size).leftJustify(colLen1));
        writef("Blocks: %-11d", stx.blocks);
        writef("IO Block: %-6d", stx.blksize);
        alias FT = FileType;
        switch(stx.type) {
            case FT.pipe:        writeln(" FIFO");                   break;
            case FT.charDevice:  writeln(" character special file"); break;
            case FT.directory:   writeln(" directory");              break;
            case FT.blockDevice: writeln(" block special file");     break;
            case FT.regularFile: writeln(" regular file");           break;
            case FT.symlink:     writeln(" symbolic link");          break;
            case FT.socket:      writeln(" socket");                 break;
            default: writefln(" unknown type (%o)", stx.mode & S_IFMT);
        }
        auto device = format!"Device: %xh/%dd"(stx.dev, stx.dev);
        writef(leftJustify(device, colLen1));
        writef("Inode: %-12d", stx.ino);
        writef("Links: %-9d", stx.nlink);  
        if (stx.type.isAmong(FileType.blockDevice, FileType.charDevice)) {
            writef(" Device type: %d,%d", stx.rdev_major, stx.rdev_minor);
        }
        writeln;
        writef!"Access: (%04o/%s)  "(
            stx.mode & octal!7777, makeUnixFileModeLine(stx.mode)
        );

        writef("Uid: (%5d/%08s)   ", stx.uid, stx.user);
        writefln("Gid: (%5d/%08s)", stx.gid, stx.group);

        string tz = getTZOffsetAsString();
        writefln("Access: %s %s", stx.atime.getTimeExtString, tz);
        writefln("Modify: %s %s", stx.mtime.getTimeExtString, tz);
        writefln("Change: %s %s", stx.ctime.getTimeExtString, tz);
        if (stx.mask & STATX_BTIME) {
            writefln(" Birth: %s %s", stx.btime.getTimeExtString, tz);
        } else {
            writefln(" Birth: -");
        }
    }
    return 0;
}
