#!/usr/bin/perl

use strict;
use warnings;
use v5.10;

use Scalar::Util qw(blessed looks_like_number);

use File::Information;

# Check which types we, only request data for installed modules.
my @as_types = qw(mediatype raw);
unshift(@as_types, 'DateTime')          if eval { require DateTime;         1 };
unshift(@as_types, 'Data::Identifier')  if eval { require Data::Identifier; 1 };

my $instance = File::Information->new;

foreach my $filename (@ARGV) {
    my $link = $instance->for_link(path => $filename, symlinks => 'follow');

    say $filename;
    say '-' x length($filename);

    dump_base(Link  => $link);
    dump_base(Inode => scalar eval {$link->inode});
    dump_base(Filesystem => scalar eval {$link->filesystem});
    dump_base(Tagpool => $_) foreach eval {$link->tagpool};
}

sub dump_base {
    my ($title, $base) = @_;
    my File::Information $instance;
    my @hashes;
    my @properties;
    my $max_len = 0;

    return unless defined $base;
    $instance   = $base->instance;
    @hashes     = sort map {$_->{name}} $base->digest_info;
    @properties = sort map {$_->{name}} $base->property_info;

    say ' ', $title;
    say ' ', '-' x length($title);

    {
        # Figure out the witdh of the key column.

        outer:
        foreach my $key (@properties) {
            foreach my $lifecycle ($instance->lifecycles) {
                my $value = $base->get($key, lifecycle => $lifecycle, default => undef, as => 'raw');
                if (defined $value) {
                    my $l = length($key);
                    $max_len = $l if $l > $max_len;
                    next outer;
                }
            }
        }

        outer:
        foreach my $algo (@hashes) {
            my $key = sprintf('digest <%s> unsafe', $algo);
            foreach my $lifecycle ($instance->lifecycles) {
                my $value = $base->digest($algo, lifecycle => $lifecycle, default => undef);
                if (defined $value) {
                    my $l = length($key);
                    $max_len = $l if $l > $max_len;
                    next outer;
                }
            }
        }
    }

    # Print properties:
    foreach my $key (@properties) {
        foreach my $lifecycle ($instance->lifecycles) {
            my $value;
            foreach my $as (@as_types) {
                $value = $base->get($key, lifecycle => $lifecycle, default => undef, as => $as);
                last if defined $value;
            }
            next unless defined $value;

            if (blessed($value)) {
                if ($value->isa('Data::Identifier')) {
                    my $id = $value;
                    $value = sprintf('%s / %s', $id->type->displayname, $id->id);
                    if (defined(my $displayname = $id->displayname(no_defaults => 1, default => undef))) {
                        $value .= sprintf(' (%s)', $displayname);
                    }
                }
            } elsif (looks_like_number($value)) {
                # no-op
            } else {
                $value = sprintf('\'%s\'', $value);
            }
            printf("  %7s :: %-*s = %s\n", $lifecycle, $max_len, $key, $value);
        }
    }

    # Print digests:
    foreach my $algo (@hashes) {
        my $key = sprintf('digest <%s>', $algo);

        $key .= ' unsafe' if $instance->digest_info($algo)->{unsafe};

        foreach my $lifecycle ($instance->lifecycles) {
            my $value = $base->digest($algo, lifecycle => $lifecycle, default => undef);
            next unless defined $value;
            printf("  %7s :: %-*s = %s\n", $lifecycle, $max_len, $key, $value);
        }
    }
}

#ll
