package MooseFS::Disk;
use strict;
use warnings;
use IO::Socket::INET;
use Moo;

extends 'MooseFS::Server';

has HDtime => (
    is => 'ro',
    default => sub { 'max' }
);

has HDperiod => ( 
    is => 'ro',
    default => sub { 'min' }
);

sub BUILD {
    my $self = shift;
    my $inforef;
    for my $ip ( keys %{ $self->info } ) {
        my $port = $self->info->{$ip}->{port};
        my $ns = IO::Socket::INET->new(
            PeerAddr => $ip,
            PeerPort => $port,
            Proto => 'tcp',
        );
        print $ns pack('(LL)>', 600, 0);
        my $nheader = $self->myrecv($ns, 8);
        my ($ncmd, $nlength) = unpack('(LL)>', $nheader);
        if ( $ncmd == 601 ) {
            my $data = $self->myrecv($ns, $nlength);
            while ( $nlength > 0 ) {
                my ($entrysize) = unpack("S>", substr($data, 0, 2));
                my $entry = substr($data, 2, $entrysize);
                $data = substr($data, 2+$entrysize);
                $nlength -= 2 + $entrysize;
            
                my $plen = ord(substr($entry, 0, 1));
                my $ip_path = sprintf "%s:%u:%s", $ip, $port, substr($entry, 1, $plen);
                my ($flags, $errchunkid, $errtime, $used, $total, $chunkscnt) = unpack("(CQLQQL)>", substr($entry, $plen+1, 33));
                my ($rbytes, $wbytes, $usecreadsum, $usecwritesum, $usecfsyncsum, $rops, $wops, $fsyncops, $usecreadmax, $usecwritemax, $usecfsyncmax);

                if ($entrysize == $plen + 34 + 144 ) {
            
                    if ($self->HDperiod eq 'min' ) {
                        ($rbytes, $wbytes, $usecreadsum, $usecwritesum, $rops, $wops, $usecreadmax, $usecwritemax) = unpack("(QQQQLLLL)>", substr($entry, $plen+34, 48));
                    } elsif ($self->HDperiod eq 'hour') {
                        ($rbytes, $wbytes, $usecreadsum, $usecwritesum, $rops, $wops, $usecreadmax, $usecwritemax) = unpack("(QQQQLLLL)>", substr($entry, $plen+34+48, 48));
                    } elsif ($self->HDperiod eq 'day') {
                        ($rbytes, $wbytes, $usecreadsum, $usecwritesum, $rops, $wops, $usecreadmax, $usecwritemax) = unpack("(QQQQLLLL)>", substr($entry, $plen+34+48+48, 48));
                    }
            
                } elsif ( $entrysize == $plen + 34 + 192 ) {
            
                    if ($self->HDperiod eq 'min' ) {
                        ($rbytes, $wbytes, $usecreadsum, $usecwritesum, $usecfsyncsum, $rops, $wops, $fsyncops, $usecreadmax, $usecwritemax, $usecfsyncmax) = unpack("(QQQQQLLLLLL)>", substr($entry, $plen+34, 64));
                    } elsif ($self->HDperiod eq 'hour') {
                        ($rbytes, $wbytes, $usecreadsum, $usecwritesum, $usecfsyncsum, $rops, $wops, $fsyncops, $usecreadmax, $usecwritemax, $usecfsyncmax) = unpack("(QQQQQLLLLLL)>", substr($entry, $plen+34+64, 64));
                    } elsif ($self->HDperiod eq 'day') {
                        ($rbytes, $wbytes, $usecreadsum, $usecwritesum, $usecfsyncsum, $rops, $wops, $fsyncops, $usecreadmax, $usecwritemax, $usecfsyncmax) = unpack("(QQQQQLLLLLL)>", substr($entry, $plen+34+64+64, 64));
                    }
            
                }
            
                my ($rtime, $wtime, $fsynctime);
                if ($self->HDtime eq 'avg') {
                    if ($rops > 0) {
                        $rtime = $usecreadsum/$rops;
                    } else {
                        $rtime = 0;
                    };
            
                    if ($wops > 0) {
                        $wtime = $usecwritesum/$wops;
                    } else {
                        $wtime = 0;
                    };
            
                    if ($fsyncops > 0) {
                        $fsynctime = $usecfsyncsum/$fsyncops;
                    } else {
                        $fsynctime = 0;
                    };
                } else {
                    $rtime = $usecreadmax;
                    $wtime = $usecwritemax;
                    $fsynctime = $usecfsyncmax;
                };
            
                my $status;
                if ($flags == 1) {
                    $status = 'marked for removal';
                } elsif ($flags == 2) {
                    $status = 'damaged';
                } elsif ($flags == 3) {
                    $status = 'damaged, marked for removal';
                } else {
                    $status = 'ok';
                };
            
                my $lerror;
                if ($errtime == 0 and $errchunkid == 0) {
                    $lerror = 'no errors';
                } else {
                    $lerror = localtime($errtime);
                };
            
                my $rbsize = $rops > 0 ? $rbytes / $rops : 0;
                my $wbsize = $wops > 0 ? $wbytes / $wops : 0;
                my $percent_used = $total > 0 ? ($used * 100.0) / $total : '-';
                my $rbw = $usecreadsum > 0 ? $rbytes * 1000000 / $usecreadsum : 0;
                my $wbw = $usecwritesum + $usecfsyncsum > 0 ? $wbytes *1000000 / ($usecwritesum + $usecfsyncsum) : 0;
            
                $self->info->{$ip} = {
                    ip_path => $ip_path,
                    flags => $flags,
                    errchunkid => $errchunkid,
                    errtime => $errtime,
                    used => $used,
                    total => $total,
                    chunkscount => $chunkscnt,
                    rbw => $rbw,
                    wbw => $wbw,
                    rtime => $rtime,
                    wtime => $wtime,
                    fsynctime => $fsynctime,
                    read_ops => $rops,
                    write_ops => $wops,
                    fsyncops => $fsyncops,
                    read_bytes => $rbytes,
                    write_bytes => $wbytes,
                    usecreadsum => $usecreadsum,
                    usecwritesum => $usecwritesum,
                    status => $status,
                    lerror => $lerror,
                    rbsize => $rbsize,
                    wbsize => $wbsize,
                    percent_used => $percent_used,
                };
            };
        }
    }
}

1;
